import {
  S3Client,
  HeadObjectCommand,
  GetObjectCommand,
  PutObjectCommand,
} from "@aws-sdk/client-s3";
import {
  ENTITY_TYPE,
  FIleLoadRes,
  MeshCreateOptions,
  FileLoadOptions,
  RemeshOptions,
  MODEL_TYPE,
  Options,
  VIEW_MODE,
  AnalysisOptions,
  MidSurfaceOptions,
  TEMPLATE_TYPE,
  IDManagerOptions,
  WasherCreateOptions,
  GetFaceIdByCellIndexResult,
  Meshextrude2dCreateOptions,
  Meshextrude2dPreviewOptions,
  Meshextrude3dCreateOptions,
  FillHoleOptions,
  EdgePartitionOptions,
  MidSurfaceThicknessOptions,
  PastenodeApplyOptions,
  FileSaveOptions,
  Sweep3dOptions,
  SelectedParts,
  TransformUpdateOptions,
  SelectedEdgeInfo,
  FreebodyReadFileOptions,
  FreebodyApplyOptions,
  FreebodyEntity,
  FreebodyFindNodesOptions,
  FreebodyEnterOptions,
  FreebodyTableDataOptions,
} from "../interface";
import { CommandHistory } from "@/FrontProcessing/Command/CommandHistory";
import { State, STATE_EVENT, STATUS_CODE } from "@/FrontProcessing/State/State";
import {
  Application,
  BActor,
  devtool,
  IMouseEvent,
  IKeyEvent,
  PointerActor,
  VTActorRenderType,
  vtxlyLoader,
  GyMesh3dLoader,
  GyMesh3DActor,
  NormalActor,
  VTActor,
  TCell,
  TArrow,
  LineActor,
} from "cax-base";
import { FrontProcessing } from "@/FrontProcessing";
import { GyActor } from "@/FrontProcessing/Actors/GyActor";
import { Cmd_Model_Add } from "@/FrontProcessing/Command/Cmd_Model_Add";
import { MeshActor } from "@/FrontProcessing/Actors/MeshActor";
import { Connector } from "cax-connector";
/****************
 * *方法导入
 ****************/
import { project_save } from "./project_save";
import { project_load } from "./project_load";
import { state_clear } from "./state_clear";
import { engine_clear } from "./engine_clear";
import { model_info } from "./model_info";
import { get_string_from_oss } from "./get_string_from_oss";
import { func_vertex_measure } from "./func/func_vertex_measure";
import {
  func_edge_selector,
  addToSelectedEdgeSetByEdgeId,
  removeFromSelectedEdgeSetByEdgeId,
  uniqueId,
} from "./func/func_edge_selector";
import { func_trim_by_nodes } from "./func/func_trim_by_nodes";
import { func_show_all_mesh } from "./func/func_show_all_mesh";
import { func_hide_all_mesh } from "./func/func_hide_all_mesh";

import { registerAll } from "@/FrontProcessing/Connector/registerAll";
import { Vector3 } from "stl-typescript";
import { MeshThicknessActor } from "../Actors/MeshThicknessActor";
import { normal_get } from "./normal_get";
import { func_mesh_edge_selector } from "./func/func_mesh_edge_selector";
import { oss, Bucket, AppEvent } from "@/UI/config";
import { parametersName } from "@/UI/components/Material/constants";
import { options } from "node_modules/axios/index.cjs";
import { getEntityIds } from "@/UI/components/sidebar/model";
import { normal_reverse } from "./normal_reverse";
import { normal_align } from "./normal_align";
import {
  get_selected_edge,
  get_selected_node,
  get_selected_face,
  get_selected_body,
  get_selected_2_faces,
} from "./select/get_selected_object";
/****************
 * *通信方法导入
 ****************/

/**
 * @class System
 * @description: 系统模块，负责管理系统的所有功能
 *
 * @param { Application } app
 * @param { FrontProcessing } parent 父级容器
 * @param { Connector } connector 连接器
 * @param { CommandHistory } history 命令历史记录管理器
 * @param { State } state 状态管理器
 * @param { Options } options 配置项
 * @param { HTMLElement} container 容器
 *
 * @param { PointerActor } _tempPointer 临时指针actor
 * @param { IMouseEvent } _rightClickCallBack_vertex_measure:  顶点测量模式下鼠标右键回调函数
 * @param _rightClickCallBack_gemo_body: Function 几何体模式下鼠标右键回调函数
 * @param _rightClickCallBack_edge: Function 边模式下鼠标右键回调函数
 * @param _rightClickCallBack_normal: Function 正常模式下鼠标右键回调函数
 * @param _leftClickCallBack: Function 鼠标左键回调函数
 * @param _keyDownCallBack: Function 键盘按下回调函数
 * @param _keyUpCallBack: Function 键盘抬起回调函数
 * @param _mousemoveCallBack_edge: Function 边模式下鼠标移动回调函数
 * @param _mousemoveCallBack_trim: Function 剪裁模式下鼠标移动回调函数
 * @param _selectPoint: Function 点选模式下鼠标右键回调函数
 * @param _escKeyDownCallBack: Function ESC键按下回调函数
 */
export class System {
  // 类的属性定义
  app: Application;
  parent: FrontProcessing;
  connector: any = new Connector();
  history: CommandHistory = new CommandHistory();
  state: State = new State();

  EDGE_SELECTED_COLOR = [255, 0, 0, 255];

  // 临时指针actor
  _tempPointer: PointerActor = new PointerActor([0, 0, 0], {
    color: [0, 0, 1],
  });

  // * 用来展示法向量的对象
  normalActor: NormalActor | null = null;

  // 回调函数 -> private callback event
  private _mousemoveCallBack_vertex_measure!: (event: IMouseEvent) => void;
  private _mousemoveCallBack_edge!: (event: IMouseEvent) => void;
  private _mousemoveCallBack_mesh_edge!: (event: IMouseEvent) => void;

  private _mousemoveCallBack_trim!: (event: IMouseEvent) => void;

  private _rightClickCallBack_vertex_measure!: (event: IMouseEvent) => void;
  private _rightClickCallBack_mesh_edge!: (event: IMouseEvent) => void;

  private _rightClickCallBack_gemo_body!: (event: IMouseEvent) => void;
  private _rightClickCallBack_edge!: (event: IMouseEvent) => void;
  private _rightClickCallBack_normal!: (event: IMouseEvent) => void;
  private _rightClickCallBack_select_point!: (event: IMouseEvent) => void;
  private _rightClickCallBack_select_single_point!: (
    event: IMouseEvent
  ) => void;
  private _rightClickCallBack_select_single_line!: (event: IMouseEvent) => void;
  private _leftClickCallBack!: (event: IMouseEvent) => void;
  private _escKeyDownCallBack!: (event: IKeyEvent) => void;

  // S3客户端
  public s3Client: any;
  // 默认为 test
  public bucket = "test";
  public endpoint = "";

  constructor(
    parent: FrontProcessing,
    container: HTMLElement,
    options: Options
  ) {
    this.parent = parent;
    this.app = new Application(container, this);
    registerAll(this.connector);
    (this.connector as Connector).connectCallBack = () => {
      this.state.pub(STATE_EVENT.CONNECT, true);
    };
    (this.connector as Connector).disconnectCallBack = () => {
      this.state.pub(STATE_EVENT.DISCONNECT, true);
    };
    this.initOptions(options);
    this.initListens();
  }

  // 初始化选项
  initOptions(options: Options) {
    // 根据环境初始化S3客户端
    this.s3Client =
      location.href.indexOf("dev") !== -1
        ? new S3Client({
            region: "us-east-1", // 区域可更改
            endpoint: "http://127.0.0.1:9000",
            credentials: {
              accessKeyId: "minioadmin",
              secretAccessKey: "minioadmin",
            },
            maxAttempts: 3,
            requestHandler: {
              connectionTimeout: 2000,
            },
          })
        : new S3Client(options.config.oss);
    this.bucket = options.config.bucket;
    this.endpoint =
      options.config.oss.endpoint.toString() ?? "http://127.0.0.1:9000";
  }

  // 初始化监听器
  initListens() {
    // 鼠标右键、鼠标移动 回调函数注册
    this.registerAllRightClickEvents();
    this.registerAllMouseMoveEvents();
    this.registerAllKeydownEvents();
  }

  // ****************鼠标事件初始化**********************
  // 初始化所有鼠标右键事件~注册
  registerAllRightClickEvents() {
    // init
    this._rightClickCallBack_vertex_measure =
      this.initVertexMeasureRightClickEvent();

    this._rightClickCallBack_gemo_body = this.initGemoBodyRightClickEvent();

    this._rightClickCallBack_normal = this.initNomalRightClickEvent();

    this._rightClickCallBack_edge = this.initEdgeRightClickEvent();

    this._rightClickCallBack_select_point =
      this.initSelectPointRightClickEvent();
    this._rightClickCallBack_mesh_edge = this.initMeshEdgeRightClickEvent();

    this._rightClickCallBack_select_single_point =
      this.initSelectSinglePointRightClickEvent();
    this._rightClickCallBack_select_single_line =
      this.initSelectSingleLineRightClickEvent();
    // register
    this.app.registerMouseRightListener(
      this._rightClickCallBack_vertex_measure
    );

    this.app.registerMouseRightListener(this._rightClickCallBack_gemo_body);

    this.app.registerMouseRightListener(this._rightClickCallBack_edge);

    this.app.registerMouseRightListener(this._rightClickCallBack_normal);
    this.app.registerMouseRightListener(this._rightClickCallBack_mesh_edge);
  }

  // 初始化所有鼠标移动事件~注册
  registerAllMouseMoveEvents() {
    // init
    this._mousemoveCallBack_vertex_measure = (event: IMouseEvent) => {
      if (this.state.modeCode === STATUS_CODE.VERTEX_MEASURE) {
        func_vertex_measure(event, this);
      }
    };
    this._mousemoveCallBack_edge = (event: IMouseEvent) => {
      if (this.state.modeCode === STATUS_CODE.EDGE) {
        func_edge_selector(event, this);
      }
    };
    this._mousemoveCallBack_mesh_edge = (event: IMouseEvent) => {
      if (this.state.modeCode === STATUS_CODE.MESH_EDGE) {
        func_mesh_edge_selector(event, this);
      }
    };
    this._mousemoveCallBack_trim = (event: IMouseEvent) => {
      if (this.state.modeCode === STATUS_CODE.TRIM) {
        func_trim_by_nodes(event, this);
      }
    };
    // register
    this.app.registerMouseMoveListener(this._mousemoveCallBack_vertex_measure);
    this.app.registerMouseMoveListener(this._mousemoveCallBack_edge);
    this.app.registerMouseMoveListener(this._mousemoveCallBack_mesh_edge);
    this.app.registerMouseMoveListener(this._mousemoveCallBack_trim);
  }
  // 初始化所有键盘事件~注册
  registerAllKeydownEvents() {
    // init
    this._escKeyDownCallBack = this.initEscKeyDownEvent(); // Esc按键

    // register
    this.app.registerKeyDownListener(this._escKeyDownCallBack);
  }

  // 初始化鼠标右键事件~~Measure
  initVertexMeasureRightClickEvent() {
    return (event: IMouseEvent) => {
      if (this.state.modeCode === STATUS_CODE.VERTEX_MEASURE) {
        // 顶点测量
        this.parent.measureComp.pointToPoint(this._tempPointer);
        const pos = event.position;
        const point: any = [pos.x, pos.y, 0.0];
        this.app.selector.vtPointPicker.pick(point, this.app.renderer);
        this.selectPoint(
          this._tempPointer.userdata.partId,
          this.state.currentSelectedPartEntityId,
          this._tempPointer.userdata.id
        );
      }
    };
  }

  // 初始化鼠标右键事件~~gemobody
  initGemoBodyRightClickEvent() {
    return (event: IMouseEvent) => {
      if (this.state.modeCode === STATUS_CODE.GEOM_BODY) {
        // 选中实体
        const pos = event.position;
        const point = [pos.x, pos.y, 0.0];
        devtool.info(`🟢 geom body 当前选择点: ${point}`);
        this.app.selector.vtPicker.pick(point, this.app.renderer);
        if (this.app.selector.vtPicker.getActors().length === 0) {
          return 0;
        } else {
          const selector = this.app.selector.getPickedVTActors() as GyActor[];
          console.log("selector", selector);
          let index = 0;
          this.app.actorList.value.forEach((q: any, i: number) => {
            if (q instanceof GyActor) {
              if (q.partId === selector[0].partId) {
                index = i;
              }
            }
          });
          this.selectPart(index, selector[0]);
          return;
        }
      }
    };
  }

  // 初始化鼠标右键事件~~normal
  initNomalRightClickEvent() {
    return (event: IMouseEvent) => {
      if (this.state.modeCode !== STATUS_CODE.NORMAL) return;
      const pos = event.position;
      const point = [pos.x, pos.y, 0.0];
      devtool.info(`🟢 当前选择点: ${point}`);
      this.app.selector.vtPicker.pick(point, this.app.renderer);
      if (this.app.selector.vtPicker.getActors().length === 0) {
        return 0;
      } else {
        const pickedCellId = this.app.selector.vtPicker.getCellId();
        devtool.info(`🟢 当前选择index: ${pickedCellId}`);
        const back = this.parent.selectorComp.getFaceIdByCellIndex(
          this.app.actorList,
          pickedCellId,
          this.state,
          this.app.selector.getPickedVTActors() as GyActor[]
        );
        console.log("back:", back);
        this.state.currentSelectedBackData = back;
        // 选择不同显示模式下 右键的选择逻辑
        // 修改 normal 模式下的 鼠标右键事件逻辑
        // 显示面 模式1：右键点击选面
        // 显示线框 模式2：选网格和网格交叉点
        if (this.state.viewMode === VIEW_MODE.SURFACE) {
          // 模式1-显示面
          if (back?.faceId) {
            if (this.state.maskFaceIds.has(back?.faceId)) {
              return;
            } else {
              this.selectFace(back, pickedCellId);
            }
          }
        } else if (this.state.viewMode === VIEW_MODE.WIREFRAME) {
          // 模式2-显示线框
          // TODO: 如果在主体actor中无法找到face的话，那么就在网格中进行查找。
          for (let i = 0; i < this.app.actorList.value.length; i++) {
            const ac = this.app.actorList.value[i];
            if (ac instanceof MeshActor && ac.isDpMesh == false) {
              if (ac.containsCellId(pickedCellId)) {
                this.selectMesh(pickedCellId);
                ac.selectCellWithDoubleClick(pickedCellId);
                break;
              }
            }
          }
        }
        this.app.window.render();
      }
      return;
    };
  }
  initMeshEdgeRightClickEvent() {
    return (event: IMouseEvent) => {
      if (this.state.modeCode === STATUS_CODE.MESH_EDGE) {
        const pos = event.position;
        const point = [pos.x, pos.y, 0.0];
        devtool.info(`🟢 mesh_edge 当前选择点: ${point}`);
        this.app.selector.vtPicker.pick(point, this.app.renderer);
        if (this.app.selector.vtPicker.getActors().length === 0) {
          return 0;
        } else {
          const modelPosition = this.app.selector.vtPicker.getMapperPosition();
          const pickedCellId = this.app.selector.vtPicker.getCellId();
          this.app.actorList.foreach((ac: any) => {
            if (ac instanceof MeshActor && ac.isDpMesh == false) {
              if (ac.containsCellId(pickedCellId)) {
                // 将网格pickedCellId转化为格宇识别的网格index
                const cellId = ac.getElemIdByCellId(pickedCellId);
                // 根据cellId 对应data中cellId找到点击的网格的顶点
                const cell = ac.getCells(cellId);
                // console.log("cell", cell);
                if (cell) {
                  const data = ac.searchMeshEdgeByPoint(modelPosition, cell);
                  if (data) {
                    //取消选中
                    if (this.state.currentSelectedMeshEdges.has(data.uid)) {
                      ac.removeMeshActor(data.uid);
                      this.state.currentSelectedMeshEdges.delete(data.uid);
                    } else {
                      // 选中
                      data.elementEdgeNodeId = data?.start[0];
                      data.elementEdgeSecondNodeId = data?.end[0];
                      this.state.currentSelectedMeshEdges.set(data.uid, data);
                      ac.setMeshEdgeColor(
                        data,
                        data?.start.slice(1),
                        data?.end.slice(1),
                        [1, 0.65, 0],
                        5
                      );
                    }
                  }
                } else {
                  devtool.warn(`🟢 nodes未定义`);
                }
              }
            }
          });
        }
      }
    };
  }
  // 初始化鼠标右键事件~Edge
  initEdgeRightClickEvent() {
    return (event: IMouseEvent) => {
      if (this.state.modeCode === STATUS_CODE.EDGE) {
        const pos = event.position;
        const point = [pos.x, pos.y, 0.0];
        devtool.info(`🟢 edge 当前选择点: ${point}`);
        this.app.selector.vtPicker.pick(point, this.app.renderer);
        if (this.app.selector.vtPicker.getActors().length === 0) {
          return 0;
        } else {
          const modelPosition = this.app.selector.vtPicker.getMapperPosition();
          const pickedCellId = this.app.selector.vtPicker.getCellId();
          devtool.info(`🟢 edge 当前选择index: ${pickedCellId}`);
          const back = this.parent.selectorComp.getFaceIdByCellIndex(
            this.app.actorList,
            pickedCellId,
            this.state,
            this.app.selector.getPickedVTActors() as GyActor[]
          );
          console.log("back", back);
          const outLinesAc = (
            this.app.selector.getPickedVTActors()[0] as VTActor
          ).outlines;
          if (!outLinesAc) {
            devtool.error("🔴 edge 没有找到outlines");
            return;
          }
          const edgeId = outLinesAc.searchEdgeByPoint(
            modelPosition,
            back.faceId
          ).selectedEdgeId;
          if (!edgeId) {
            devtool.error("🔴 edge 没有id");
            return;
          }
          this.selectEdge(back, modelPosition, pickedCellId, edgeId);
        }
      }
    };
  }

  // 初始化~鼠标右键select point
  initSelectPointRightClickEvent() {
    return (event: IMouseEvent) => {
      const pos = event.position;
      const point = [pos.x, pos.y, 0.0];
      this.app.selector.vtPicker.pick(point, this.app.renderer);
      if (this.app.selector.vtPicker.getActors().length === 0) {
        return 0;
      } else {
        const pickedCellId = this.app.selector.vtPicker.getCellId();
        const vtPickerPos = this.app.selector.vtPicker.getMapperPosition(); // 鼠标位置映射坐标
        // 计算与鼠标点击位置 距离最近的Vertex
        for (let i = 0; i < this.app.actorList.value.length; i++) {
          const ac = this.app.actorList.value[i];
          if (ac instanceof MeshActor && ac.isDpMesh == false) {
            const node = ac.nearestPoint(vtPickerPos);
            this.selectMeshPoint(node.nodeId, ac.partId);
            ac.selectNodeWithDoubleClick(node);
          }
        }
        this.app.window.render();
      }
      return;
    };
  }
  initSelectSinglePointRightClickEvent() {
    return (event: IMouseEvent) => {
      const pos = event.position;
      const point = [pos.x, pos.y, 0.0];
      this.app.selector.vtPicker.pick(point, this.app.renderer);
      if (this.app.selector.vtPicker.getActors().length === 0) {
        return 0;
      } else {
        // 获取点击位置的世界坐标
        const coordinate = this.app.selector.vtPicker.getMapperPosition();
        console.log("选中的三维坐标:", coordinate);
        const selectedPointCoordinate =
          this.app.currentSelectSinglePointCoordinate;
        let selectedPointActor = this.app.currentSelectedSinglePointActor;
        if (selectedPointActor) {
          this.parent.model.remove(selectedPointActor);
        }
        selectedPointActor = new PointerActor(coordinate, {
          color: [1, 0, 0],
          radius: 0.8,
        });
        this.parent.model.add(selectedPointActor);
        this.setSelectSinglePoint(coordinate, selectedPointActor);
      }
    };
  }
  initSelectSingleLineRightClickEvent() {
    return (event: IMouseEvent) => {
      const pos = event.position;
      const point = [pos.x, pos.y, 0.0];
      this.app.selector.vtPicker.pick(point, this.app.renderer);
      if (this.app.selector.vtPicker.getActors().length === 0) {
        return 0;
      } else {
        const coordinate = this.app.selector.vtPicker.getMapperPosition();
        console.log("选中的线三维坐标:", coordinate);
        const selectedPointCoordinate =
          this.app.currentSelectSinglePointCoordinate;
        let selectedPointActor = this.app.currentSelectedSinglePointActor;
        const selectedLineCoordinate =
          this.app.currentSelectSingleLineCoordinate || [];
        const selectedLineActor = this.app.currentSelectedSingleLineActor;
        if (selectedLineCoordinate.length % 6 < 3) {
          if (selectedLineActor) {
            this.parent.model.remove(selectedLineActor);
            this.setSelectSingleLine([], null);
          }
          if (selectedPointActor) {
            this.parent.model.remove(selectedPointActor);
          }
          selectedPointActor = new PointerActor(coordinate, {
            color: [1, 0, 0],
            radius: 0.8,
          });
          this.parent.model.add(selectedPointActor);
          this.setSelectSinglePoint(coordinate, selectedPointActor);
          this.setSelectSingleLine(coordinate, null);
        } else {
          const coordinate1 = this.app.currentSelectSinglePointCoordinate;
          const coordinate2 = coordinate;
          //创建杆的效果
          const uid = "line" + coordinate1 + "_" + coordinate2;
          const color: [number, number, number] = [0, 0, 0];
          const lineActor = new LineActor(
            [coordinate1[0], coordinate1[1], coordinate1[2]],
            coordinate2,
            { uid },
            { color }
          );
          this.parent.model.add(lineActor);
          this.setSelectSingleLine(coordinate, lineActor);
          if (selectedPointActor) {
            this.parent.model.remove(selectedPointActor);
          }
          this.setSelectSinglePoint([], null);
        }
      }
    };
  }
  // ****************鼠标事件增删**********************
  // 所有鼠标右键事件移除
  // unregisterGlobalRightClick() {
  //   this.app.clearMouseRightButtonPress();
  // }
  // 所有鼠标移动事件移除
  // unregisterGlobalMosuseMove() {
  //   this.app.clearMouseRightButtonPress();
  // }
  // 键盘事件注册~Esc
  initEscKeyDownEvent() {
    return (event: IKeyEvent) => {
      this.state.pub(STATE_EVENT.ESCKEYDOWN, true);
      return;
    };
  }
  // 鼠标右键事件注册，此处只注册normal事件
  registerNormalRightClick() {
    if (!this.app.hasMouseDownEvent(this._rightClickCallBack_normal)) {
      this.registerEvent(this._rightClickCallBack_normal, "rightClick");
    }
  }

  // 鼠标右键事件移除，此处只移除normal事件
  unregisterNormalRightClick() {
    if (this.app.hasMouseDownEvent(this._rightClickCallBack_normal)) {
      this.unregisterEvent(this._rightClickCallBack_normal, "rightClick");
    }
  }

  // 鼠标右键事件注册，此处只注册SelectPoint事件
  registerSelectPointRightClick() {
    if (!this.app.hasMouseDownEvent(this._rightClickCallBack_select_point)) {
      this.registerEvent(this._rightClickCallBack_select_point, "rightClick");
    }
  }

  //鼠标右键事件注册，此处只注册选面上任意点事件
  registerSelectSinglePointRightClick() {
    if (
      !this.app.hasMouseDownEvent(this._rightClickCallBack_select_single_point)
    ) {
      this.registerEvent(
        this._rightClickCallBack_select_single_point,
        "rightClick"
      );
    }
  }
  //鼠标右键事件注册，此处只注册选面上任意线事件
  registerSelectSingleLineRightClick() {
    if (
      !this.app.hasMouseDownEvent(this._rightClickCallBack_select_single_line)
    ) {
      this.registerEvent(
        this._rightClickCallBack_select_single_line,
        "rightClick"
      );
    }
  }

  // 鼠标右键事件移除，此处只移除SelectPoint事件
  unregisterSelectPointRightClick() {
    if (this.app.hasMouseDownEvent(this._rightClickCallBack_select_point)) {
      this.unregisterEvent(this._rightClickCallBack_select_point, "rightClick");
    }
  }

  unregisterSelectSinglePointRightClick() {
    if (
      this.app.hasMouseDownEvent(this._rightClickCallBack_select_single_point)
    ) {
      this.unregisterEvent(
        this._rightClickCallBack_select_single_point,
        "rightClick"
      );
    }
  }
  unregisterSelectSingleLineRightClick() {
    if (
      this.app.hasMouseDownEvent(this._rightClickCallBack_select_single_line)
    ) {
      this.unregisterEvent(
        this._rightClickCallBack_select_single_line,
        "rightClick"
      );
    }
  }

  // 取消注册base
  unregisterEvent(event: (event: any) => void, type: string) {
    switch (type) {
      case "mouseMove":
        this.app.unregisterMouseMoveListener(event);
        break;
      case "rightClick":
        this.app.unregisterMouseRightListener(event);
        break;
      case "keyDown":
        this.app.unregisterKeyDownListener(event);
        break;
    }
  }

  // 注册base
  registerEvent(event: (event: any) => void, type: string) {
    switch (type) {
      case "mouseMove":
        this.app.registerMouseMoveListener(event);
        break;
      case "rightClick":
        this.app.registerMouseRightListener(event);
        break;
      case "mouseDown":
        this.app.registerKeyDownListener(event);
        break;
    }
  }

  // 选择部件
  selectPart(index: number, selector: GyActor) {
    const selectedColor = [0, 255, 0, 255];
    const delPart = this.state.currentDeletedParts.filter(
      (delItem: any) => delItem.partId === selector.partId
    );
    const back = this.parent.selectorComp.getPartIdByCellIndex(
      delPart[0],
      selector
    );

    if (this.state.currentSelectedPartIds.has(back.partId)) {
      // * 🐷 取消选中
      this.state.currentSelectedPartId = -1;
      this.state.currentSelectedPartEntityId = -1;
      this.state.currentSelectedPartIds.delete(back.partId);
      this.state.currentSelectedPartEntityIds.delete(back.partEntityId);
      this.splice_dict_array(back.partId, back.partEntityId, [], [], []);
      this.app.actorList.value[index].setCells2defaultColor(back.triangleIds);
    } else {
      // * 🐷 选中
      this.state.currentSelectedPartId = back.partId;
      this.state.currentSelectedPartEntityId = back.partEntityId;
      this.state.currentSelectedPartIds.add(back.partId);
      this.state.currentSelectedPartEntityIds.add(back.partEntityId);
      this.state.currentSelectedParts = this.merge_dict_array(
        this.state.currentSelectedParts,
        back.partId,
        back.partEntityId,
        [],
        [],
        []
      );
      this.app.actorList.value[index].setCellsColor(
        back.triangleIds,
        selectedColor
      );
    }
    this.app.window.render();
  }

  // 选择面
  selectFace(back: any, pickedCellId: any) {
    const selectedColor = [0, 255, 0, 255];
    this.state.currentSelectedActorId = back.actorIndex;
    if (this.state.currentSelectedFaceIds.has(back.faceId)) {
      // * 🐷 取消选中
      this.app.currentSelectFaceId = -1;
      this.state.currentSelectedPartId = -1;
      this.state.currentSelectedPartIds.delete(back.partId);
      this.state.currentSelectedFaceIds.delete(back.faceId);
      const flag = this.isContainFace(back);
      if (flag) {
        // 清除part相关选择内容
        this.splice_dict_array(
          back.partId,
          back.partEntityId,
          [back.faceId],
          back.triangleIds,
          []
        );
        back.triangleIds.forEach((item: number) =>
          this.state.currentSelectedTriangleIds.delete(item)
        );
        console.log("back", back);
        this.app.actorList.value[back.actorIndex].setCells2defaultColor(
          back.triangleIds
        );
        devtool.info("🟢 取消所选单元: ", pickedCellId, "face id", back.faceId);
      }
    } else {
      // * 🐷 选中
      this.state.currentSelectedFaceIds.add(back.faceId);
      this.state.currentSelectedPartId = back.partId;
      this.state.currentSelectedPartIds.add(back.partId);
      back.triangleIds.forEach((item: number) =>
        this.state.currentSelectedTriangleIds.add(item)
      );
      const flag = this.isContainFace(back);
      if (flag) {
        this.state.currentSelectedFaceIds.add(back.faceId);
        this.state.currentSelectedPartId = back.partId;
        this.state.currentSelectedPartIds.add(back.partId);
        back.triangleIds.forEach((item: number) =>
          this.state.currentSelectedTriangleIds.add(item)
        );
        // 添加part相关选择内容
        this.state.currentSelectedParts = this.merge_dict_array(
          this.state.currentSelectedParts,
          back.partId,
          back.partEntityId,
          [back.faceId],
          back.triangleIds,
          []
        );
        this.app.actorList.value[back.actorIndex].setCellsColor(
          back.triangleIds,
          selectedColor
        );

        this.app.currentSelectFaceId = back.faceId;
        devtool.info(
          "🟢 当前所选单元索引: ",
          pickedCellId,
          "face id",
          this.app.currentSelectFaceId
        );
      }
    }
  }

  // 选边
  selectEdge(
    back: GetFaceIdByCellIndexResult,
    modelPosition: [number, number, number],
    edgeIndex: number,
    edgeId: number
  ) {
    const selectedColor = [255, 0, 0, 255];
    const unselectedColor = [0, 0, 0, 255];
    const uid = uniqueId(edgeId, back.faceId, back.partId);
    if (
      JSON.stringify(this.state.currentSelectedEdgeOriginColor) ===
      JSON.stringify(selectedColor)
    ) {
      // * 🐷 取消选中
      this.state.currentSelectedEdgeStartIndex = -1;
      this.state.currentSelectedEdgeEndIndex = -1;
      this.state.currentSelectedEdgeOriginColor = unselectedColor;
      this.state.currentSelectedPartId = -1;
      this.state.currentSelectedPartEntityId = -1;
      this.app.actorList.value.forEach((actor: any) => {
        if (actor.isGyActor && actor.partId === back.partId) {
          actor.outlines.setEdgeColor(
            modelPosition,
            back.faceId,
            unselectedColor
          );
        }
      });
      removeFromSelectedEdgeSetByEdgeId(this, uid);
    } else {
      // * 🐷 选中
      this.app.actorList.value.forEach((actor: any) => {
        if (actor.isGyActor && actor.partId === back.partId) {
          const selectedEdgeIndexDict = actor.outlines.setEdgeColor(
            modelPosition,
            back.faceId,
            selectedColor
          );
          const {
            selectedEdgeStartIndex,
            selectedEdgeEndIndex,
            selectedEdgeOriginColor,
          } = selectedEdgeIndexDict;
          this.state.currentSelectedEdgeStartIndex = selectedEdgeStartIndex;
          this.state.currentSelectedEdgeEndIndex = selectedEdgeEndIndex;
          this.state.currentSelectedEdgeOriginColor = selectedEdgeOriginColor;
          this.state.currentSelectedPartId = back.partId;
          this.state.currentSelectedPartEntityId = back.partEntityId;
        }
      });
      this.app.actorList.value.forEach((actor: any) => {
        if (actor.isGyActor && actor.partId === back.partId) {
          actor.outlines.setEdgeColor(
            modelPosition,
            back.faceId,
            selectedColor
          );
        }
      });
      addToSelectedEdgeSetByEdgeId(this, uid, {
        edgeIndex,
        edgeId,
        faceId: back.faceId,
        partId: back.partId,
      });
    }
    this.app.window.render();
  }

  /**
   * @description 通过api设置选中的轮廓线
   * @param cellIndexArr {} 真正的单元索引数组 一条曲线可能由很多条直线组成
   */
  setSelectEdgeByEdgeId(
    edgeIndex: number,
    edgeId: number,
    faceId: number,
    partId: number,
    cellIndexArr: number[]
  ) {
    // * 数据状态变更
    const uid = uniqueId(edgeId, faceId, partId);
    addToSelectedEdgeSetByEdgeId(this, uid, {
      edgeIndex,
      edgeId,
      faceId,
      partId,
    });

    // * 渲染状态变更
    this.app.actorList.value.forEach((actor: any) => {
      if (actor.partId === partId) {
        (actor as VTActor).outlines?.setEdgesColorByEdgeIndex(
          cellIndexArr,
          this.EDGE_SELECTED_COLOR
        );
      }
    });
  }

  // 选取点，将信息记录至state中
  selectPoint(partId: number, partEntityId: number, vertexId: number) {
    if (
      this.state.currentSelectedVertexIds.has({
        id: vertexId,
        partId: partId,
      })
    ) {
      this.state.currentSelectedVertexId = -1;
      this.state.currentSelectedPartId = -1;
      this.state.currentSelectedPartEntityId = -1;
      this.state.currentSelectedVertexIds.delete({
        id: vertexId,
        partId: partId,
      });
      this.splice_dict_array(
        partId,
        partEntityId,
        [],
        [],
        [
          {
            vertexId: vertexId,
            partEntityId: partEntityId,
            partId: partId,
          },
        ]
      );
    } else {
      this.state.currentSelectedPartId = partId;
      this.state.currentSelectedPartEntityId = partEntityId;
      this.state.currentSelectedVertexId = vertexId;
      this.state.currentSelectedVertexIds.add({
        id: vertexId,
        partId: partId,
      });
      // 添加part相关选择内容
      this.state.currentSelectedParts = this.merge_dict_array(
        this.state.currentSelectedParts,
        partId,
        partEntityId,
        [],
        [],
        [
          {
            vertexId: vertexId,
            partEntityId: partEntityId,
            partId: partId,
          },
        ]
      );
    }
  }

  // 检查是否包含面
  isContainFace(back: any) {
    let flag = true;
    this.state.currentDeletedParts.every((item: any) => {
      if (
        item.partId === back.partId &&
        item.faceIds.indexOf(back.faceId) !== -1
      ) {
        flag = false;
        return false;
      }
      return true;
    });
    return flag;
  }

  // 选择网格
  selectMesh(pickedCellId: any) {
    for (let i = 0; i < this.app.actorList.value.length; i++) {
      const ac = this.app.actorList.value[i];
      if (ac instanceof MeshActor && ac.isDpMesh == false) {
        if (ac.containsCellId(pickedCellId)) {
          // 将网格pickedCellId转化为格宇识别的网格index
          const index = ac.getElemIdByCellId(pickedCellId);
          this.state.currentSelectedMeshPartId = ac.partId;
          this.selector_select_mesh_by_click(index);
          break;
        }
      }
    }
  }

  // 选择meshPoint
  selectMeshPoint(nodeId: number, partId: number) {
    if (this.state.currentSelectedMeshPointIds.has(nodeId)) {
      this.state.currentSelectedMeshPointIds.delete(nodeId);
      this.state.currentSelectedMeshPointIdMapPartId.delete(nodeId);
      this.app.currentSelectMeshPointId = -1;
    } else {
      this.state.currentSelectedMeshPointIds.add(nodeId);
      this.state.currentSelectedMeshPointIdMapPartId.set(nodeId, partId);
      this.app.currentSelectMeshPointId = nodeId;
    }
  }

  //选择点
  // 选择meshPoint
  setSelectSinglePoint(coordinate: number[], pointActor: any) {
    this.app.currentSelectSinglePointCoordinate = coordinate;
    this.app.currentSelectedSinglePointActor = pointActor;
  }
  getSelectedSinglePoint() {
    const coordinate = this.app.currentSelectSinglePointCoordinate;
    const pointActor = this.app.currentSelectedSinglePointActor;
    return { coordinate, pointActor };
  }
  //选择线
  setSelectSingleLine(coordinate: number[], lineActor: any) {
    if (coordinate.length === 0) {
      this.app.currentSelectSingleLineCoordinate = [];
    } else {
      if (!this.app.currentSelectSingleLineCoordinate) {
        this.app.currentSelectSingleLineCoordinate = [];
      }
      this.app.currentSelectSingleLineCoordinate.push(...coordinate);
    }
    this.app.currentSelectedSingleLineActor = lineActor;
  }
  getSelectedSingleLine() {
    const lineCoordinate = this.app.currentSelectSingleLineCoordinate;
    const lineActor = this.app.currentSelectedSingleLineActor;
    return { lineCoordinate, lineActor };
  }
  // 每次取消选择后删除相同实体下的不同面、点
  splice_dict_array(
    partId: number,
    partEntityId: number,
    faceIds: number[],
    triangleIds: number[],
    vertexIds: any[]
  ) {
    let parts = this.state.currentSelectedParts;
    if (parts.length > 0) {
      const tempParts: any = [];
      parts.every((part: any, index: number) => {
        if (part.partId === partId) {
          part.partEntityId = partEntityId;
          part.faceIds.splice(part.faceIds.indexOf(faceIds[0]), 1);
          part.triangleIds = part.triangleIds.filter(
            (tId: any) => !triangleIds.includes(tId)
          );
          part.vertexIds = part.vertexIds.filter(
            (vId: any) => !vertexIds.includes(vId)
          );
          return false;
        }
        if (
          part.faceIds.length !== 0 &&
          part.triangleIds.length !== 0 &&
          part.vertexIds.length !== 0
        ) {
          tempParts.push(part);
        }
        return true;
      });
      parts = [...tempParts];
    }
  }

  // 每次选择后合并相同实体下的不同面
  merge_dict_array(
    parts: any[],
    partId: number,
    partEntityId: number,
    faceIds: number[],
    triangleIds: number[],
    vertexIds: any[]
  ) {
    const actor = {
      partId,
      partEntityId,
      faceIds,
      triangleIds,
      vertexIds,
    };
    if (parts.length > 0) {
      let flag = true;
      parts.every((part: any) => {
        if (part.partId === partId) {
          part.partEntityId = actor.partEntityId;
          part.faceIds = part.faceIds.concat(actor.faceIds);
          part.triangleIds = part.triangleIds.concat(actor.triangleIds);
          part.vertexIds = part.vertexIds.concat(actor.vertexIds);
          flag = false;
          return false;
        }
        return true;
      });
      if (flag) {
        parts.push(actor);
      }
    } else {
      parts.push(actor);
    }
    return parts;
  }

  // 添加实体
  async add_entity(
    entityId: number,
    entityType: number,
    partId: number
  ): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector
        .add_entity(entityId, entityType, partId)
        .then((result: boolean) => {
          if (result) {
            this.clear_all_selected();
            // 完成后端删除后，完成UI的网格清除。
            this.parent.meshComp.clearMesh();
          }
          resolve(result);
        });
    });
  }

  // 删除实体
  delete_entity(parts: any[], type: number): Promise<number> {
    return new Promise((resolve) => {
      this.connector.delete_entity(parts, type).then((res: any) => {
        resolve(res);
      });
    });
  }

  // 计数孔
  counter_bore(): Promise<any> {
    return new Promise((resolve) => {
      this.connector
        .counter_bore(this.state.currentSelectedParts)
        .then((result: FIleLoadRes) => {
          console.log("counter_bore_res", result);
          try {
            this.app.actorList.foreach((ele: any) => {
              if (!(ele instanceof MeshActor && ele.isDpMesh == false)) {
                this.parent.ModelComp.engine.model.remove(ele);
              }
            });
            this.load_file_from_S3(result);
            this.clear_selected_state();
            resolve(result.BomInfo);
          } catch (err) {
            console.error("Error downloading file:", err);
          }
        });
    });
  }

  // 倒圆角面
  face_fillet(): Promise<any> {
    return new Promise((resolve) => {
      this.connector
        .face_fillet(this.state.currentSelectedParts)
        .then((result: FIleLoadRes) => {
          console.log("face_fillet_res", result);
          this.app.actorList.foreach((ele: any) => {
            this.parent.ModelComp.engine.model.remove(ele);
          });
          try {
            this.load_file_from_S3(result);
            this.clear_selected_state();
            resolve(result.BomInfo);
          } catch (err) {
            console.error("Error downloading file:", err);
          }
        });
    });
  }

  // 分析孔
  analysis_hole(options: AnalysisOptions): Promise<any> {
    return new Promise((resolve) => {
      this.connector.analysis_hole(options).then((result: FIleLoadRes) => {
        console.log("analysis_hole_res", result);
        resolve(result);
      });
    });
  }
  mid_surface_thickness(options: MidSurfaceThicknessOptions): Promise<any> {
    options.partId = this.state.currentSelectedPartId;
    options.meshIds = Array.from(this.state.currentSelectedMeshIds);
    options.meshPartId = this.state.currentSelectedMeshPartId;
    return new Promise((resolve) => {
      this.connector.mid_surface_thickness(options).then((result: any) => {
        try {
          // 返回中面网格厚度值
          console.log("result", result);
          const pointsData: number[][][] = [];
          this.app.actorList.foreach((ac: any) => {
            if (ac instanceof MeshActor && ac.isDpMesh == false) {
              Array.from(ac.cellIds).forEach((cellId) =>
                ac.faceData.data.forEach((q) => {
                  if (q.cellId === cellId + 1) {
                    const filteredNodes = q.nodes.map((nodeArray) =>
                      nodeArray.slice(1)
                    );
                    pointsData.push(filteredNodes);
                  }
                })
              );
            }
          });
          this.parent.model.add(new MeshThicknessActor(pointsData, result));
          this.state.midSurfaceThicknessPointsData = pointsData;
          this.state.midSurfaceThickness = result;
          resolve(result);
        } catch (err) {
          console.error("Error downloading file:", err);
        }
      });
    });
  }
  show_mid_surface_thickness(value: boolean) {
    console.log("value", value, this.app.graphicActorList);
    if (value) {
      this.parent.model.add(
        new MeshThicknessActor(
          this.state.midSurfaceThicknessPointsData,
          this.state.midSurfaceThickness
        )
      );
    } else {
      this.app.graphicActorList.foreach((ac: any) => {
        if (ac instanceof MeshThicknessActor) {
          this.parent.model.remove(ac);
        }
      });
    }
  }
  edge_partition(options: EdgePartitionOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      const { currentSelectedEdges } = this.state;
      if (currentSelectedEdges.size == 0) {
        reject(currentSelectedEdges.size);
        return;
      }
      const edges = [...currentSelectedEdges.values()];
      this.connector
        .edge_partition({ meshCtrl: options, edges })
        .then((result: any) => {
          try {
            for (const edgeId in result) {
              const points = result[edgeId].points;
              const vectors = Array.from(
                { length: Math.floor(points.length / 3) },
                (_, i) =>
                  new Vector3(
                    points[i * 3],
                    points[i * 3 + 1],
                    points[i * 3 + 2]
                  )
              );
              vectors.map((value) => {
                return this.parent.model.add(
                  new PointerActor([value.x, value.y, value.z], {
                    color: [0, 1, 0],
                    radius: 0.5,
                  })
                );
              });
            }
            resolve(result);
          } catch (err) {
            console.error("Error downloading file:", err);
          }
        });
    });
  }
  edge_mesh_bias(options: {
    entityId: number[];
    meshCtrl: EdgePartitionOptions;
  }): Promise<any> {
    return new Promise((resolve, reject) => {
      this.connector.edge_mesh_bias(options).then((result: any) => {
        try {
          for (const edgeId in result) {
            const willRemoveAc = this.app.graphicActorList.value.filter(
              (gActor: any) =>
                gActor.userdata.bias && gActor.userdata.edgeId === edgeId
            );
            willRemoveAc.length &&
              willRemoveAc.forEach((gActor: any) =>
                this.parent.model.remove(gActor)
              );
            const { nodes, points } = result[edgeId];
            const vectors = Array.from(
              { length: Math.floor(points.length / 3) },
              (_, i) =>
                new Vector3(points[i * 3], points[i * 3 + 1], points[i * 3 + 2])
            );
            vectors.map((value, i) => {
              const point = new PointerActor([value.x, value.y, value.z], {
                color: [1, 0, 1],
                radius: 0.3,
              });
              point.userdata = { bias: true, edgeId, node: nodes[i] };
              return this.parent.model.add(point);
            });
          }
          resolve(result);
        } catch (err) {
          console.error("Error downloading file:", err);
        }
      });
    });
  }
  edge_get_ratio(ratioType: number): Promise<any> {
    return new Promise((resolve, reject) => {
      const { currentSelectedEdges } = this.state;
      if (currentSelectedEdges.size == 0) {
        reject(currentSelectedEdges.size);
        return;
      }
      const edges = [...currentSelectedEdges.values()];
      this.connector
        .edge_get_ratio({ edgeId: edges[0].edgeId, ratioType })
        .then((result: any) => {
          console.log("--- get ratio: ", result);
          resolve(result);
        });
    });
  }
  edge_mesh_leave(options?: string): Promise<any> {
    return new Promise((resolve, reject) => {
      this.connector.edge_mesh_leave(options).then((result: any) => {
        this.clear_all_selected();
        resolve(result);
      });
    });
  }

  // 中间面
  mid_surface(options: MidSurfaceOptions): Promise<any> {
    return new Promise((resolve) => {
      options.partId = this.state.currentSelectedPartId;
      options.partEntityId = this.state.currentSelectedPartEntityId;
      if (options.partId === -1) {
        console.log("请先选择一个实体");
      }
      this.connector.mid_surface(options).then((result: FIleLoadRes) => {
        console.log("mid_surface_res", result);
        try {
          this.app.actorList.foreach((ele: any) => {
            if (!(ele instanceof MeshActor && ele.isDpMesh == false)) {
              this.parent.ModelComp.engine.model.remove(ele);
            }
          });
          this.load_file_from_S3(result);
          this.clear_selected_state();
          resolve(result.BomInfo);
        } catch (err) {
          console.error("Error downloading file:", err);
        }
      });
    });
  }

  id_manager(options: IDManagerOptions): Promise<any> {
    return new Promise((resolve) => {
      this.connector.id_manager(options).then((result: FIleLoadRes) => {
        console.log("id_manager_res", result);
        try {
          this.app.actorList.foreach((ele: any) => {
            if (!(ele instanceof MeshActor && ele.isDpMesh == false)) {
              this.parent.ModelComp.engine.model.remove(ele);
            }
          });
          this.load_file_from_S3(result);
          this.clear_selected_state();
          resolve(result.BomInfo);
        } catch (err) {
          console.error("Error downloading file:", err);
        }
      });
    });
  }

  // 加载文件
  file_load(
    path: string,
    type: MODEL_TYPE,
    callback?: (p: number) => void
  ): Promise<any> {
    return new Promise((resolve) => {
      let reader: any;
      switch (type) {
        case "vtu":
          break;
        // case "vtp":
        //   reader = vtkXMLPolyDataReader.newInstance();
        //   reader
        //     .setUrl(path, {
        //       progressCallback: (ev: any) => {
        //         const p = Math.ceil((ev.loaded * 100) / ev.total);
        //         callback && callback(p);
        //       },
        //     })
        //     .then(() => {
        //       const source = reader.getOutputData(0);
        //       resolve(new VTActor(source));
        //     });
        //   break;
        // case "stl":
        //   reader = vtkSTLReader.newInstance();
        //   reader
        //     .setUrl(path, {
        //       progressCallback: (ev: any) => {
        //         const p = Math.ceil((ev.loaded * 100) / ev.total);
        //         callback && callback(p);
        //       },
        //     })
        //     .then(() => {
        //       const source = reader.getOutputData();
        //       resolve(new VTActor(source));
        //     });
        //   break;
        case "gy":
          console.log("path:", path);
          this.connector
            .file_load(path, type)
            .then(async (result: FIleLoadRes) => {
              // 将fetch处理替换为minio上获取的文件内容
              console.log("result", result);
              // 初始化 S3 客户端
              const s3Client = this.s3Client;
              const bucketName = this.bucket;
              const objectKey = result["FilePath"];
              let BomInfo: any[] = [];
              const GeoData: any[] = [];
              // 从minio上获取文件流
              const command = new GetObjectCommand({
                Bucket: bucketName,
                Key: objectKey,
              });
              const getFilePromise = s3Client
                .send(command)
                .then((response: any) => {
                  console.log("download response", response);
                  return response.Body?.transformToString();
                })
                .then((strPromise: any) => {
                  const itemDataStringArr: string[] = JSON.parse(
                    strPromise as string
                  );
                  for (let i = 0; i < itemDataStringArr.length; i++) {
                    GeoData.push(new vtxlyLoader(itemDataStringArr[i]));
                  }
                });

              // 获取BomInfo
              const command2 = new GetObjectCommand({
                Bucket: bucketName,
                Key: result["BomInfo"],
              });
              const getBomInfoPromise = s3Client
                .send(command2)
                .then((BomInfoResult: any) => {
                  return BomInfoResult.Body?.transformToString();
                })
                .then((strPromiseForBom: any) => {
                  if (strPromiseForBom) {
                    BomInfo = JSON.parse(strPromiseForBom);
                    this.parent.dataComp.setBomData(result.BomInfo);
                  }
                });
              Promise.all([getFilePromise, getBomInfoPromise]).then(() => {
                resolve({
                  BomInfo: BomInfo,
                  PartIds: result.PartIds,
                  GeoData: GeoData,
                });
              });
            });
          break;
        case "test_gy":
          fetch(path)
            .then((response) => response.text())
            .then((data) => {
              const itemDataStringArr: string[] = JSON.parse(data as string);
              console.log("itemDataStringArr", itemDataStringArr);
              resolve(itemDataStringArr);
            });
          break;
      }
    });
  }

  private handleViewMode() {
    const viewMode = this.get_state("ViewMode");
    isString(viewMode) && this.view_change_mode(viewMode);
    // 类型守卫
    function isString(value: unknown): value is string {
      return typeof value === "string";
    }
  }

  private updateMesh(
    _this: any,
    json: string,
    lineWidth: number,
    color: any,
    isDuplicate: boolean
  ) {
    const ac = _this.parent.meshComp.gyMeshToActor(
      json,
      lineWidth,
      color,
      isDuplicate
    );
    ac.meshActor.setParent(this.parent);
    _this.parent.meshComp.updateMesh(ac.meshActor, ac.meshActor.partId);

    this.handleViewMode();
  }

  mesh_update(_this: any, json: string, lineWidth: number, color: any) {
    this.updateMesh(_this, json, lineWidth, color, false);
  }

  dp_mesh_update(_this: any, json: string, lineWidth: number, color: any) {
    this.updateMesh(_this, json, lineWidth, color, true);
  }

  /**
   * stp_file_load
   * @description: 加载stp文件或者bdf文件
   */
  stp_or_bdf_file_load(options: FileLoadOptions): Promise<any> {
    return new Promise((resolve) => {
      console.log("--- stp_or_bdf_file_load: ", options);
      this.connector
        .file_load(options.type, {
          ...options,
          type: options.importType,
        })
        .then(async (result: FIleLoadRes) => {
          console.log(`Processing file with importType: ${options.importType}`);
          //
          //处理几何文件
          if (options.importType == TEMPLATE_TYPE.GEOMETRY) {
            try {
              this.load_file_from_S3(result);
              get_string_from_oss(this, result.BomInfo).then((str) => {
                resolve(JSON.parse(str));
              });
            } catch (err) {
              console.error("Error downloading file:", err);
            }
          } else {
            // nastran装载网格
            console.log(" importType:", options.importType);
            console.log("res from load:", result);
            get_string_from_oss(this, result.FilePath)
              .then((json: string) => {
                this.mesh_update(this, json, 4, [0, 0, 1]);
                this.clear_all_selected();
              })
              .then(() => {
                get_string_from_oss(this, result.BomInfo).then((str) => {
                  resolve(JSON.parse(str));
                });
              });
          }
        });
    });
  }

  // 从S3加载文件
  load_file_from_S3(result: FIleLoadRes) {
    // 初始化 S3 客户端
    const s3Client = this.s3Client;
    const bucketName = this.bucket;
    const objectKey = result["FilePath"];

    console.log("原始文件路径:", objectKey);
    // 从minio上获取文件流
    const command = new GetObjectCommand({
      Bucket: bucketName,
      Key: objectKey,
    });
    return new Promise((resolve) => {
      s3Client
        .send(command)
        .then((response: any) => {
          return response.Body?.transformToString();
        })
        .then((strPromise: any) => {
          const itemDataStringArr: string[] = JSON.parse(strPromise as string);
          this.parent.ModelComp.stp_file_load(itemDataStringArr, result);
          resolve(result);
        });
    });
  }

  // 清除选中状态
  clear_selected_state() {
    this.state.currentSelectedParts = [];
    this.state.currentSelectedFaceIds.clear();
    this.state.currentSelectedActors.empty();
    this.state.currentSelectedTriangleIds.clear();
    this.state.currentSelectedPartIds.clear();
    this.state.currentSelectedPartEntityIds.clear();
    this.state.currentSelectedPartEntityId = -1;
    this.state.currentSelectedActorId = -1;
    this.state.currentSelectedPartId = -1;
    this.state.currentSelectedFaceId = -1;
    this.state.currentSelectedEdges.clear(); // 做修剪功能时补加的代码
    this.state.currentSelectedParts = []; // 做修剪功能时补加的代码
  }

  file_save(params: FileSaveOptions): Promise<string> {
    return new Promise((resolve) => [
      this.connector.file_save(params).then((path: string) => {
        resolve(path);
      }),
    ]);
  }
  // 下载原始模型
  model_save(filename: string, toType: string): Promise<string> {
    return new Promise((resolve) => [
      this.connector.model_save(filename, toType).then((path: string) => {
        resolve(path);
      }),
    ]);
  }

  // 添加模型
  model_add(actor: BActor) {
    new Cmd_Model_Add(this, actor).execute();
  }

  // 删除模型
  model_remove(actor: BActor) {
    this.app.remove(actor);
  }

  // 清除所有模型
  model_clear() {
    this.app.clear();
  }

  // 隐藏模型
  model_mask(partId: number) {
    // 隐藏在app层实现
    this.app.mask(partId);
  }

  // 显示模型
  model_unmask(partId: number) {
    this.app.unmask(partId);
  }

  async delete_mesh(): Promise<boolean> {
    const partId = (this.state.currentSelectedActors.value[0] as GyActor)
      .partId;
    console.log("delete mesh in system.");
    return new Promise((resolve) => {
      this.connector.delete_mesh(partId).then((result: boolean) => {
        if (result) {
          this.clear_all_selected();
          // 完成后端删除后，完成UI的网格清除。
          this.parent.meshComp.clearMesh();
        }

        resolve(result);
      });
    });
  }

  entity_delete(value: number): Promise<boolean> {
    return new Promise((resolve) => {
      // 面
      const { currentSelectedPartIds, currentSelectedParts } = this.state;
      if (value === ENTITY_TYPE.FACE) {
        const back = this.state.currentSelectedBackData;
        this.delete_entity(currentSelectedParts, value).then((res) => {
          if (res === 0) {
            this.app.actorList.value.forEach((actor: any) => {
              currentSelectedParts.forEach((part: any) => {
                if (actor instanceof GyActor) {
                  if (part.partId === actor.partId) {
                    actor.setCellsColor([...part.triangleIds], [0, 0, 0, 0]);
                  }
                }
              });
            });
            const delIndexList = this.state.currentDeletedParts.map(
              (delItem: any) => {
                return delItem.partId;
              }
            );
            this.state.currentSelectedParts.map((selItem: any) => {
              if (delIndexList.indexOf(selItem.partId) !== -1) {
                this.state.currentDeletedParts = this.merge_dict_array(
                  this.state.currentDeletedParts,
                  selItem.partId,
                  selItem.partEntityId,
                  selItem.faceIds,
                  selItem.triangleIds,
                  selItem.vertexIds
                );
              } else {
                this.state.currentDeletedParts.push(selItem);
              }
            });
            this.clear_selected_state();
            this.app.window.render();
          }
        });
      }
      // 实体
      if (value === ENTITY_TYPE.GEOM_BODY) {
        this.delete_entity(currentSelectedParts, value).then((res) => {
          if (res === 0) {
            this.app.actorList.foreach((ac: any) => {
              if (ac instanceof GyActor) {
                if (currentSelectedPartIds.has(ac.partId)) {
                  ac.visible = false;
                  if (ac.outlines) {
                    ac.outlines.visible = false;
                  }
                }
              }
            });
            this.clear_selected_state();
            this.app.window.render();
          }
        });
      }
      // 点
      if (value === ENTITY_TYPE.VERTEX) {
        this.delete_entity(currentSelectedParts, value).then(() => {
          this.app.graphicActorList.value.map((gActor: any) => {
            console.log(gActor);
            if (Object.keys(gActor).indexOf("userdata") !== -1) {
              if (
                this.state.currentSelectedVertexIds.has({
                  id: gActor.userdata.id,
                  partId: gActor.userdata.id,
                })
              ) {
                gActor.visible = false;
              }
            }
          });
          this.clear_selected_state();
          this.app.window.render();
          // this.parent.measureComp.engine.model.remove();
        });
      }
      this.app.window.render();
      resolve(true);
    });
  }
  setFaceDefaultColor() {
    this.app.actorList.foreach((actor: any) => {
      if (actor instanceof GyActor) {
        actor.setDefaultFaceColor([255, 255, 0]);
      }
    });
  }
  async mesh_offset(options: any): Promise<any> {
    return new Promise((resolve) => {
      options.partId = this.state.currentSelectedMeshPartId;
      options.meshIds = Array.from(this.state.currentSelectedMeshIds);
      this.connector.mesh_offset(options).then(async (result: any) => {
        const loader = new GyMesh3dLoader();
        await loader.load(result.FilePath);
        const ac = new GyMesh3DActor(loader);
        ac.setRenderType(VTActorRenderType.SURFACE_WITH_EDGE);
        this.app.add(ac);
        this.clear_all_selected();
        resolve(true);
      });
    });
  }
  async wrapper_mesh_create(options: any): Promise<any> {
    return new Promise((resolve) => {
      options.partId = this.state.currentSelectedPartId;
      this.connector.wrapper_mesh_create(options).then(async (result: any) => {
        const loader = new GyMesh3dLoader();
        await loader.load(result.FilePath);
        const ac = new GyMesh3DActor(loader);
        ac.setRenderType(VTActorRenderType.SURFACE_WITH_EDGE);
        this.app.add(ac);
        this.clear_all_selected();
        resolve(true);
      });
    });
  }
  async cfd_mesh_create(options: any): Promise<any> {
    return new Promise((resolve) => {
      options.partId = this.state.currentSelectedPartId;
      options.faceId = this.app.currentSelectFaceId;
      this.connector.cmf_mesh_create(options).then((result: any) => {
        try {
          if (options.action === "mesh") {
            const loader = new GyMesh3dLoader();
            loader.load(result.FilePath).then(() => {
              const ac = new GyMesh3DActor(loader);
              ac.setRenderType(VTActorRenderType.SURFACE_WITH_EDGE);
              this.app.add(ac);
              this.clear_all_selected();
              resolve(true);
            });
          } else {
            resolve(result);
          }
        } catch (err) {
          console.error("Error downloading file:", err);
        }
      });
    });
  }
  async mesh_organized(options: any): Promise<any> {
    return new Promise((resolve) => {
      options.meshIds = Array.from(this.state.currentSelectedMeshIds);
      options.partId = this.state.currentSelectedPartId;
      this.connector.mesh_organized(options).then((result: FIleLoadRes) => {
        try {
          this.app.actorList.foreach((ac: any) => {
            if (ac instanceof MeshActor && ac.isDpMesh == false) {
              ac.setMeshElementColor();
            }
          });
          this.load_file_from_S3(result);
          this.state.reset();
          resolve(result.BomInfo);
        } catch (err) {
          console.error("Error downloading file:", err);
        }
      });
    });
  }

  async mesh_create(options: MeshCreateOptions): Promise<boolean> {
    const faceIds = Array.from(this.state.currentSelectedFaceIds);
    let partId: number;
    if (options.entityId) {
      partId = options.entityId;
    } else {
      partId = (this.state.currentSelectedActors.value[0] as GyActor).partId;
    }
    let faceId = -1;
    for (let i = 0; i < faceIds.length - 1; i++) {
      faceId = faceIds[i];
      await this.connector.mesh_create(
        partId,
        faceId,
        options.surfaceMeshOptions,
        options.curveMeshOptions,
        options.isSubdivision
      );
    }
    faceId = faceIds[faceIds.length - 1];
    console.log("last face id: ", faceId);
    return new Promise((resolve) => {
      this.connector
        .mesh_create(
          partId,
          faceId,
          options.surfaceMeshOptions,
          options.curveMeshOptions,
          options.isSubdivision
        )
        .then((result: any) => {
          console.log("mesh_create result:", result);
          // TODO: 参考此步
          // return fetch(path, { mode: "cors" });
          get_string_from_oss(this, result.fileName).then((json: string) => {
            this.mesh_update(this, json, 4, [0, 0, 1]);
            this.clear_all_selected();
            resolve(true);
          });
        });
    });
  }

  async merge_mesh(
    partId: number,
    cellId1: number,
    cellId2: number
  ): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector
        .merge_mesh(partId, cellId1, cellId2)
        .then((path: string) => {
          return fetch(path);
        })
        .then((response: any) => response.text())
        .then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          this.clear_all_selected();
          resolve(true);
        });
    });
  }

  async mesh_remesh(options: RemeshOptions): Promise<boolean> {
    const meshIds = Array.from(this.state.currentSelectedMeshIds);
    let partId: number;
    if (options.entityId) {
      partId = options.entityId;
    } else {
      partId = (this.state.currentSelectedActors.value[0] as GyActor).partId;
    }
    const meshSize = options.meshSize ?? 1;
    const eleType = options.eleType ?? "Tri/Quad";
    const sizeType = options.sizeType ?? "Percent of BBox";
    const refinementParams = options.refinementParams ?? [];

    return new Promise((resolve) => {
      this.connector
        .mesh_remesh(
          partId,
          meshIds,
          meshSize,
          eleType,
          sizeType,
          refinementParams
        )
        .then((path: string) => {
          return fetch(path);
        })
        .then((response: any) => response.text())
        .then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          this.clear_all_selected();
          resolve(true);
        });
    });
  }
  async check_free_edge(data: any): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector
        .check_free_edge(data)
        .then((path: any) => {
          return fetch(path.FilePath);
        })
        .then((response: any) => response.text())
        .then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          this.clear_all_selected();
          resolve(true);
        });
    });
  }
  async fill_hole(data: FillHoleOptions): Promise<boolean> {
    return new Promise((resolve, reject) => {
      const { currentSelectedParts } = this.state;
      if (currentSelectedParts.length == 0) {
        reject(false);
        return;
      }
      this.connector
        .fill_hole({ parts: currentSelectedParts, param: data })
        .then((result: any) => {
          console.log("fill_hole result:", result);
          get_string_from_oss(this, result.fileName).then((json: string) => {
            this.mesh_update(this, json, 4, [0, 0, 1]);
            this.clear_all_selected();
            resolve(true);
          });
        });
    });
  }
  async join_mesher(): Promise<boolean> {
    return new Promise((resolve, reject) => {
      const { currentSelectedMeshEdges } = this.state;
      console.log("currentSelectedMeshEdges : ", currentSelectedMeshEdges);
      if (currentSelectedMeshEdges.size == 0) {
        reject(false);
        return;
      }
      const params = [...currentSelectedMeshEdges.values()].map((item) => ({
        // entityId: item.cellId,
        partId: item.partId,
        nodeId: item.elementEdgeNodeId,
        node2Id: item.elementEdgeSecondNodeId,
      }));
      this.connector.join_mesher(params).then((result: any) => {
        console.log("join_mesher result:", result);
        get_string_from_oss(this, result.fileName).then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          // this.clear_all_selected();
          this.parent.measureComp.clearMeasureActors();
          this.state.currentSelectedMeshEdges.clear();
          resolve(true);
        });
      });
    });
  }

  tetmesh_create(options: any): Promise<boolean> {
    const partId = 1;
    return new Promise((resolve) => {
      this.connector
        .create_tetmesh(partId, options)
        .then((path: string) => {
          return fetch(path);
        })
        .then((response: any) => response.text())
        .then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          this.clear_all_selected();
          resolve(true);
        });
    });
  }
  private handleOutlines(ac: any, visible: boolean) {
    if (ac.outlines) ac.outlines.visible = visible;
  }

  private handleVertexAc(ac: any, visible: boolean) {
    if (ac.vertexAc) ac.vertexAc.visible = visible;
  }

  view_change_mode(mode: VIEW_MODE) {
    this.app.actorList.foreach((ac: any) => {
      const isMesh = ac.isMesh;

      switch (mode) {
        case VIEW_MODE.SURFACE:
          if (!isMesh) {
            this.app.selector.addToTargetList(ac);
            ac.setRenderType(VTActorRenderType.SURFACE);
            this.handleOutlines(ac, true);
            this.handleVertexAc(ac, false);
          } else {
            this.app.selector.removeFromTargetList(ac);
          }
          break;

        case VIEW_MODE.WIREFRAME:
          if (!isMesh) {
            this.app.selector.removeFromTargetList(ac);
            ac.visible = false;
            this.handleOutlines(ac, true);
          } else {
            this.app.selector.addToTargetList(ac);
          }
          break;

        case VIEW_MODE.POINTS:
          if (!isMesh) {
            ac.visible = true;
            this.handleOutlines(ac, true);
            this.handleVertexAc(ac, true);
          }
          break;
      }
    });

    this.app.render();
  }

  set_state(key: string, value: any) {
    switch (key) {
      // 功能模式 normal/measure/...
      case "Mode":
        this.state.modeCode = value;
        break;
      // 显示模式 surface/wireframe/points/...
      case "ViewMode":
        this.state.viewMode = value;
        break;
    }
  }

  get_state(key: string) {
    switch (key) {
      // 功能模式 normal/measure/...
      case "Mode":
        return this.state.modeCode;
      // 显示模式 surface/wireframe/points/...
      case "ViewMode":
        return this.state.viewMode;
      case "currentSelectedEdges":
        return this.state.currentSelectedEdges;
    }
  }

  measure_p2p(id1: number, id2: number, partId1: number, partId2: number) {
    return this.connector.measure_point_to_point(id1, id2, partId1, partId2);
  }

  mask() {
    this.state.currentSelectedFaceIds.forEach((id) => {
      this.state.maskFaceIds.add(id);
    });
    this.app.actorList.foreach((ac: any) => {
      if (ac instanceof GyActor) {
        // 哪一个actor是主场景？原来actorList[0]是主场景。
        ac.hindFaces(this.state.maskFaceIds);
      }
    });
    this.state.currentSelectedFaceIds.clear();
    this.app.render();
    // return this.connector.mask(faceId);
  }

  unmaskAll() {
    this.app.actorList.value.forEach((value: any) => {
      if (value instanceof GyActor) {
        value.unmaskFaces(this.state.maskFaceIds);
      }
    });
    this.state.maskFaceIds.clear();
    this.app.render();
    // return this.connector.unmaskAll();
  }

  reverse() {
    return this.connector.reverse();
  }

  reverseAll() {
    return this.connector.reverseAll();
  }

  model_info() {
    return model_info(this);
  }

  selector_select_mesh_by_click(index: number) {
    if (this.state.currentSelectedMeshIds.has(index)) {
      this.state.currentSelectedMeshIds.delete(index);
      this.app.currentSelectMeshId = -1;
    } else {
      this.state.currentSelectedMeshIds.add(index);
      this.app.currentSelectMeshId = index;
    }
  }

  selector_select_mesh_by_box(index: number) {
    if (!this.state.currentSelectedMeshIds.has(index)) {
      this.state.currentSelectedMeshIds.add(index);
      this.app.currentSelectMeshId = index;
    }
  }

  selector_select_mesh_point_by_click(index: number) {
    if (this.state.currentSelectedMeshPointIds.has(index)) {
      this.state.currentSelectedMeshPointIds.delete(index);
      this.app.currentSelectMeshPointId = -1;
    } else {
      this.state.currentSelectedMeshPointIds.add(index);
      this.app.currentSelectMeshPointId = index;
    }
  }

  selector_select_mesh_point_by_box(index: number) {
    if (!this.state.currentSelectedMeshPointIds.has(index)) {
      this.state.currentSelectedMeshPointIds.add(index);
      this.app.currentSelectMeshPointId = index;
    }
  }

  clear_all_selected() {
    this.app.actorList.foreach((ac: any) => {
      // console.log("ac", ac);
      if (ac instanceof MeshActor && ac.isDpMesh == false) {
        ac.unselectAllElements();
        ac.unselectAllMeshPoints();
        this.parent.selectBoxComp.resetSelectedMeshPoint();
      } else {
        //清除面相关变量信息并恢复默认色
        ac.resetCellsColor();
        this.app.currentSelectFaceId = -1;
        this.state.currentSelectedPartIds.clear();
        this.state.currentSelectedFaceIds.clear();
        //清除线相关变量信息并恢复默认色
        ac.outlines?.hiddenEdgeColor();
        this.state.currentSelectedEdgeStartIndex = -1;
        this.state.currentSelectedEdgeEndIndex = -1;
        this.state.currentSelectedEdgeOriginColor = [0, 0, 0, 255];
        this.state.currentSelectedEdges.clear();
        //清除实体相关变量信息并恢复默认色
        this.state.currentSelectedPartId = -1;
        this.state.currentSelectedPartEntityId = -1;
        this.state.currentSelectedPartIds.clear();
        this.state.currentSelectedPartEntityIds.clear();
        //清除模型默认点相关变量信息并恢复默认色
        this.state.currentSelectedVertexId = -1;
        this.state.currentSelectedVertexIds.clear();
      }
    });
    this.state.currentSelectedParts = [];
    // this.state.currentSelectedFaceIds.clear();
    this.state.currentSelectedMeshIds.clear();
    this.state.currentSelectedMeshPointIds.clear();
    this.state.currentSelectedMeshEdges.clear();
    this.parent.measureComp.clearMeasureActors();
    this.app.render();
  }

  connect(name: string, url: string, path?: string) {
    console.log("财财是我谁", path);
    this.connector.connect(name, url, {
      path,
    });
  }

  disconnect() {
    this.connector.disconnect();
  }

  view_auto_adapt() {
    this.app.renderer.resetCamera();
    this.app.renderAtOnce();
  }
  set_edge_color(v: boolean) {
    this.app.actorList.foreach((ac: any) => {
      if (ac instanceof VTActor) {
        if (v) {
          ac.outlines?.showEdgeColor();
        } else {
          ac.outlines?.hiddenEdgeColor();
        }
      }
    });
    this.app.renderAtOnce();
  }

  create_load_constraints(values: any) {
    return this.connector.create_load_constraints(values);
  }

  create_bcs(values: any) {
    return this.connector.create_bcs(values);
  }

  create_force(values: any) {
    return this.connector.create_force(values);
  }

  create_temperature_set(values: any) {
    return this.connector.create_temperature_set(values);
  }
  delete_temperature_set(id: number) {
    return this.connector.delete_temperature_set(id);
  }

  modify_force(values: any) {
    return this.connector.modify_force(values);
  }

  modify_displacement(values: any) {
    return this.connector.modify_displacement(values);
  }

  modify_temperature(id: number, values: any) {
    return this.connector.modify_temperature(id, values);
  }

  set_temperature(node: any, values: any) {
    return this.connector.set_temperature(node, values);
  }

  delete_force_set(values: any) {
    return this.connector.delete_force_set(values);
  }

  delete_item(values: any) {
    return this.connector.delete_item(values);
  }

  add_normal(values: any) {
    this.app.add(values);
  }

  create_displacement(values: any) {
    return this.connector.create_displacement(values);
  }

  get_force_info(id: any) {
    return this.connector.get_force_info(id);
  }

  get_displacement_info(id: any) {
    return this.connector.get_displacement_info(id);
  }

  get_all_load_constraints() {
    return this.connector.get_all_load_constraints();
  }

  get_all_materials() {
    return this.connector.get_all_materials();
  }

  batch_rename_materials(prefix: any, suffix: any, materials: any) {
    return this.connector.batch_rename_materials(prefix, suffix, materials);
  }

  create_material(values: any) {
    return this.connector.create_material(values);
  }

  delete_material(id: number) {
    return this.connector.delete_material(id);
  }

  get_material_by_id(id: number) {
    return this.connector.get_material_by_id(id);
  }

  modify_material(id: number, values: any) {
    return this.connector.modify_material(id, values);
  }

  get_all_sets() {
    return this.connector.get_all_sets();
  }

  create_set(values: any) {
    return this.connector.create_set(values);
  }

  delete_set(id: number) {
    return this.connector.delete_set(id);
  }

  get_set_by_id(id: number) {
    return this.connector.get_set_by_id(id);
  }

  modify_set(id: number, values: any) {
    return this.connector.modify_set(id, values);
  }

  add_set(values: any, sets: any) {
    return this.connector.add_set(values, sets);
  }

  plot_nodeSet() {
    const nodes = this.parent.selectBoxComp.selectedPoints.map((value) => {
      return {
        x: value.x,
        y: value.y,
        z: value.z,
      };
    });
    nodes.map((value) => {
      return this.parent.model.add(
        new PointerActor([value.x, value.y, value.z], {
          color: [1, 1, 1],
          radius: 0.8,
        })
      );
    });
  }

  plot_elementSet() {
    const elements: any[] = [];
    let cellIds: any[] = [];
    this.parent.meshComp.meshActorMap.forEach((ac) => {
      if (ac instanceof MeshActor) {
        const faceData = ac.faceData;
        cellIds = Array.from(ac.cellIds);
        cellIds.forEach((item) => {
          const elemId = ac.getElemIdByCellId(item);
          const elem = faceData.getCellsFromFaceData(elemId);
          const element = {
            elemId: elem.cellId,
            partId: elem.partId,
          };
          elements.push(element);
          this.selectMesh(item);
          ac.selectCellWithDoubleClick(item);
          ac.setCellColor(item, [255, 228, 196, 255]);
        });
        this.clear_all_selected();
      }
    });
    return elements;
  }

  get_all_properties() {
    return this.connector.get_all_properties();
  }

  create_property(values: any) {
    return this.connector.create_property(values);
  }

  delete_property(id: number) {
    return this.connector.delete_property(id);
  }

  get_property_by_id(id: number) {
    return this.connector.get_property_by_id(id);
  }

  modify_property(id: number, values: any) {
    return this.connector.modify_property(id, values);
  }

  assign_property(entity_ids: number[], prop_id: number) {
    return this.connector.assign_property(entity_ids, prop_id);
  }

  batch_rename_properties(prefix: any, suffix: any, properties: any) {
    return this.connector.batch_rename_properties(prefix, suffix, properties);
  }
  get_all_outputblocks() {
    return this.connector.get_all_outputblocks();
  }

  create_outputblock(values: any) {
    return this.connector.create_outputblock(values);
  }

  delete_outputblock(id: number) {
    return this.connector.delete_outputblock(id);
  }

  get_outputblock_by_id(id: number) {
    return this.connector.get_outputblock_by_id(id);
  }

  modify_outputblock(id: number, values: any) {
    return this.connector.modify_outputblock(id, values);
  }

  assign_outputblock(entity_ids: number[], prop_id: number) {
    return this.connector.assign_outputblock(entity_ids, prop_id);
  }

  get_all_cards() {
    return this.connector.get_all_cards();
  }

  get_elements() {
    return this.connector.get_elements();
  }

  create_card(values: any) {
    return this.connector.create_card(values);
  }

  delete_card(id: number) {
    return this.connector.delete_card(id);
  }

  get_card_by_id(id: number) {
    return this.connector.get_card_by_id(id);
  }

  modify_card(id: number, values: any) {
    return this.connector.modify_card(id, values);
  }

  assign_card(entity_ids: number[], prop_id: number) {
    return this.connector.assign_card(entity_ids, prop_id);
  }

  get_all_coordinates() {
    return this.connector.get_all_coordinates();
  }

  create_coordinate(values: any) {
    return this.connector.create_coordinate(values);
  }
  create_nodeCoordinate(values: any) {
    return this.connector.create_nodeCoordinate(values);
  }
  create_materialOrientation(values: any) {
    return this.connector.create_materialOrientation(values);
  }
  delete_coordinate(id: number) {
    return this.connector.delete_coordinate(id);
  }
  delete_nodeCoordinate(id: number) {
    return this.connector.delete_nodeCoordinate(id);
  }
  set_nodeCoordinate(node: any, values: any) {
    return this.connector.set_nodeCoordinate(node, values);
  }
  delete_materialOrientation(id: number) {
    return this.connector.delete_nodeCoordinate(id);
  }
  get_coordinate_by_id(id: number) {
    return this.connector.get_coordinate_by_id(id);
  }

  modify_coordinate(nodes_info: any, name: string, setName: string) {
    return this.connector.modify_coordinate(nodes_info, name, setName);
  }
  modify_coordinatename(id: number, values: any) {
    return this.connector.modify_coordinatename(id, values);
  }
  modify_nodeCoordinate(id: number, values: any) {
    return this.connector.modify_nodeCoordinate(id, values);
  }
  modify_materialOrientation(id: number, values: any) {
    return this.connector.modify_materialOrientation(id, values);
  }
  create_rod_unit(rodNode1: any, rodNode2: any, rodUnitType: any) {
    return this.connector.create_rod_unit(rodNode1, rodNode2, rodUnitType);
  }
  create_beam_byNode(leftNode: any, rightNode: any, values: any) {
    return this.connector.create_beam_byNode(leftNode, rightNode, values);
  }

  create_beam_byLine(values: any) {
    values.lineIds = [...this.state.currentSelectedEdges.values()].map(
      (v) => v.edgeId
    );
    values.partId = [...this.state.currentSelectedEdges.values()][0].partId;
    this.state.currentSelectedEdges.clear(); // 清除边集合，防止重复创建
    return this.connector.create_beam_byLine(values);
  }
  undo_beam(values: any) {
    return this.connector.undo_beam(values);
  }
  create_field(values: any) {
    return this.connector.create_field(values);
  }
  delete_field(id: number) {
    return this.connector.delete_field(id);
  }
  modify_field(id: number, values: any) {
    return this.connector.modify_field(id, values);
  }
  add_field_nodes(nodes: any, values: any) {
    return this.connector.add_field_nodes(nodes, values);
  }
  async load2minio(filename: string, arrayBuffer: ArrayBuffer) {
    // 上传文件到 MinIO
    const key = `csv/${filename}`;
    const fileExists = await this.checkIfFileExists(Bucket(), key);
    if (!fileExists) {
      const uint8Array = new Uint8Array(arrayBuffer);
      await this.uploadFile(uint8Array, Bucket(), key);
    }
    // coreStore.setFilename(filename); // 每次上传文件修改store中的filename
    const path = `${oss().endpoint}/${Bucket()}/${key}`;
    if (path == undefined) {
      alert("path == undefined文件上传失败，请重试。");
      return;
    }
    return path;
  }
  checkIfFileExists = async (bucketName: string, objectKey: string) => {
    try {
      const command = new HeadObjectCommand({
        Bucket: bucketName,
        Key: objectKey,
      });
      await this.s3Client.send(command);
      return true;
    } catch (error: any) {
      if (error.name === "NotFound") {
        return false;
      }
      throw error;
    }
  };
  uploadFile = async (
    file: Uint8Array,
    bucketName: string,
    objectKey: string
  ) => {
    const command = new PutObjectCommand({
      Bucket: bucketName,
      Key: objectKey,
      Body: file,
    });
    try {
      const response = await this.s3Client.send(command);
      return {
        Location: `${
          location.href.includes("dev")
            ? "http://127.0.0.1:9000"
            : oss().endpoint
        }/${Bucket()}/${objectKey}`,
      };
    } catch (error) {
      alert(`文件上传失败，请重试。${error}`);
      return;
    }
  };
  upload_field_file(fileName: string, name: any, id: any) {
    return this.connector.upload_field_file(fileName, name, id);
  }
  set_entity_color(entity_id: number, rgb: number[]) {
    this.app.set_entity_color(entity_id, rgb);
  }

  project_save() {
    return project_save(this);
  }

  project_load(file: File) {
    return project_load(this, file)
      .then((res: any) => {
        return this.load_file_from_S3(res);
      })
      .then((res: any) => {
        return get_string_from_oss(this, res.BomInfo);
      })
      .then((str: string) => {
        // TODO
        console.log("BomInfo", str);
        const BomInfo = JSON.parse(str);
        this.parent.dataComp.setBomData(BomInfo);
      });
  }

  state_clear() {
    return state_clear();
  }

  engine_clear() {
    engine_clear(this);
  }

  // 清除所有内容
  clearAll() {
    state_clear();
    engine_clear(this);
  }
  re_number(data: any) {
    return new Promise((resolve) => {
      this.connector
        .re_number(data)
        .then((path: string) => {
          return fetch(path, { mode: "cors" });
        })
        .then((response: any) => response.text())
        .then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          resolve(true);
        });
    });
  }
  create_cell(data: any) {
    return new Promise((resolve) => {
      this.connector.create_cell(data).then((result: any) => {
        get_string_from_oss(this, result.fileName).then((json: string) => {
          // 创建cell
          this.mesh_update(this, json, 4, [0, 0, 1]);
          resolve(true);
        });
      });
    });
  }
  mesh_split(values: any) {
    return new Promise((resolve) => {
      this.connector
        .mesh_split(values)
        .then((path: any) => {
          const filePath = path["FilePath"];
          return fetch(filePath, { mode: "cors" });
        })
        .then((response: any) => response.text())
        .then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          resolve(true);
        });
    });
  }
  // 网格分离
  mesh_detach() {
    const meshIds = Array.from(this.state.currentSelectedMeshIds);
    const partId = (this.state.currentSelectedActors.value[0] as GyActor)
      .partId;
    return new Promise((resolve) => {
      this.connector
        .mesh_detach(meshIds, partId)
        .then((path: any) => {
          const filePath = path["FilePath"];
          return fetch(filePath, { mode: "cors" });
        })
        .then((response: any) => response.text())
        .then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          resolve(true);
        });
    });
  }
  async washer_select(): Promise<boolean> {
    return new Promise((resolve, reject) => {
      const { currentSelectedParts, currentSelectedEdges } = this.state;
      if (
        currentSelectedEdges.size === 0 &&
        currentSelectedParts.length === 0
      ) {
        reject(0);
        return;
      }
      const param: { parts?: any[]; edges?: any[] } = {};
      if (currentSelectedParts.length) {
        param["parts"] = [];
        currentSelectedParts.forEach(({ faceIds, partId }) => {
          faceIds.forEach((faceId) => {
            param["parts"]?.push({ faceId, partId });
          });
        });
      }
      if (currentSelectedEdges.size) {
        param["edges"] = [...currentSelectedEdges.values()];
      }
      this.connector
        .washer_select(
          param
          // {
          // parts: [{faceId: 1, partId: 1}],
          // edges: [{edgeId: 5, partId: 1}, {edgeId: 6, partId: 1}]
          // }
        )
        .then((result: boolean) => {
          console.log("---- washer select result", result);
          resolve(result);
        });
    });
  }
  async washer_create(options: WasherCreateOptions): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.washer_create(options).then((result: boolean) => {
        console.log("---- create washer result");
        this.clear_all_selected();
        resolve(result);
      });
    });
  }

  async washer_clear(options?: WasherCreateOptions): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.washer_clear(options).then((result: boolean) => {
        console.log("---- clear washer result");
        this.clear_all_selected();
        resolve(result);
      });
    });
  }

  async washer_find(options: WasherCreateOptions): Promise<any> {
    return new Promise((resolve) => {
      this.connector.washer_find(options).then((result: any) => {
        this.clear_all_selected();
        resolve(result.Result);
      });
    });
  }

  async washer_hole(options: WasherCreateOptions): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.washer_hole(options).then((result: any) => {
        console.log("---- washer_hole result");
        this.clear_all_selected();
        resolve(result);
      });
    });
  }

  async washer_leave(): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.washer_leave().then((result: boolean) => {
        console.log("---- washer_leave result");
        this.clear_all_selected();
        if (this.state.currentSelectedEdges.size > 0) {
          this.state.currentSelectedEdges.clear();
        }
        resolve(result);
      });
    });
  }

  async washer_enter(): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.washer_enter().then((result: boolean) => {
        console.log("---- washer_enter result");
        resolve(result);
      });
    });
  }

  async meshextrude2d_leave(options?: string): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.meshextrude2d_leave(options).then((result: boolean) => {
        if (
          options === "dragbynode" &&
          this.state.currentSelectedMeshPointIds.size > 0
        ) {
          this.parent.selectBoxComp.resetSelectedMeshPoint();
          this.state.currentSelectedMeshPointIds.clear();
          this.state.currentSelectedMeshPointIdMapPartId.clear();
          this.app.currentSelectMeshPointId = -1;
        } else if (
          options === "dragbycurve" &&
          this.state.currentSelectedEdges.size > 0
        ) {
          this.clear_all_selected();
        }
        resolve(result);
      });
    });
  }

  async meshextrude2d_clear(options?: string): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.meshextrude2d_clear(options).then((result: boolean) => {
        if (
          options === "dragbynode" &&
          this.state.currentSelectedMeshPointIds.size > 0
        ) {
          this.parent.selectBoxComp.resetSelectedMeshPoint();
          this.state.currentSelectedMeshPointIds.clear();
          this.state.currentSelectedMeshPointIdMapPartId.clear();
          this.app.currentSelectMeshPointId = -1;
        } else if (
          options === "dragbycurve" &&
          this.state.currentSelectedEdges.size > 0
        ) {
          this.state.currentSelectedEdges.clear();
        }
        resolve(result);
      });
    });
  }

  async meshextrude2d_update_method(options?: string): Promise<boolean> {
    return new Promise((resolve) => {
      if (
        options === "dragbycurve" &&
        this.state.currentSelectedMeshPointIds.size > 0
      ) {
        this.parent.selectBoxComp.resetSelectedMeshPoint();
        this.state.currentSelectedMeshPointIds.clear();
        this.state.currentSelectedMeshPointIdMapPartId.clear();
        this.app.currentSelectMeshPointId = -1;
      } else if (
        options === "dragbynode" &&
        this.state.currentSelectedEdges.size > 0
      ) {
        this.state.currentSelectedEdges.clear();
      }
      this.connector
        .meshextrude2d_update_method(options)
        .then((result: boolean) => {
          resolve(result);
        });
    });
  }

  async meshextrude2d_create(
    options: Meshextrude2dCreateOptions
  ): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.meshextrude2d_create(options).then((result: any) => {
        if (options.method === "dragbynode") {
          this.parent.selectBoxComp.resetSelectedMeshPoint();
          this.state.currentSelectedMeshPointIds.clear();
          this.state.currentSelectedMeshPointIdMapPartId.clear();
          this.app.currentSelectMeshPointId = -1;
        } else {
          this.clear_all_selected();
        }
        get_string_from_oss(this, result.fileName).then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          resolve(true);
        });
      });
    });
  }

  async meshextrude2d_preview(
    options: Meshextrude2dPreviewOptions
  ): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.meshextrude2d_preview(options).then((result: boolean) => {
        console.log("---- meshextrude2d_preview result");
        resolve(result);
      });
    });
  }

  async meshextrude2d_add_entity(method?: string): Promise<any> {
    return new Promise((resolve, reject) => {
      const {
        currentSelectedEdges,
        currentSelectedMeshPointIds,
        currentSelectedMeshPointIdMapPartId,
      } = this.state;
      if (
        (method === "dragbycurve" && currentSelectedEdges.size === 0) ||
        (method === "dragbynode" && currentSelectedMeshPointIds.size < 2)
      ) {
        reject(false);
        return;
      }
      const params =
        method === "dragbycurve"
          ? [...currentSelectedEdges.values()].map(({ partId, edgeId }) => ({
              entityId: edgeId,
              partId,
              entityType: ENTITY_TYPE.EDGE,
            }))
          : [...currentSelectedMeshPointIds.values()].map((nodeId) => ({
              entityId: nodeId,
              partId: currentSelectedMeshPointIdMapPartId.get(nodeId),
              entityType: 64,
            }));
      this.connector
        .meshextrude2d_add_entity(params)
        .then((result: boolean) => {
          resolve(result);
        });
    });
  }

  // 三维拉伸
  async meshextrude3d_update_method(options?: string): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector
        .meshextrude3d_update_method(options)
        .then((result: boolean) => {
          console.log("---- meshextrude3d_update_method result");
          resolve(result);
        });
    });
  }
  async meshextrude3d_add_entity(method?: string): Promise<any> {
    return new Promise((resolve, reject) => {
      const { currentSelectedMeshIds, currentSelectedPartId } = this.state;
      if (
        method === "dragbyshellmesh" &&
        currentSelectedMeshIds.size === 0
        // || (method === "dragbyfacesfromsolid" && currentSelectedMeshPointIds.size < 2)
      ) {
        reject(false);
        return;
      }
      const params =
        method === "dragbyshellmesh"
          ? [...currentSelectedMeshIds.values()].map((entityId) => ({
              entityFaceIndex: 0,
              entityId: entityId,
              entityType: 4,
              partId: 1,
            }))
          : [...currentSelectedMeshIds.values()].map((entityId) => ({
              entityFaceIndex: 0,
              entityId: entityId,
              entityType: 1024,
              partId: 1,
            }));
      this.connector
        .meshextrude3d_add_entity(params)
        .then((result: boolean) => {
          resolve(result);
        });
    });
  }

  async meshextrude3d_leave(options?: string): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.meshextrude3d_leave(options).then((result: boolean) => {
        console.log("---- meshextrude3d_leave result");
        this.clear_all_selected();
        resolve(result);
      });
    });
  }

  async meshextrude3d_clear(options?: string): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.meshextrude3d_clear(options).then((result: boolean) => {
        console.log("---- meshextrude3d_clear result");
        this.clear_all_selected();
        resolve(result);
      });
    });
  }

  async meshextrude3d_create(
    options: Meshextrude3dCreateOptions
  ): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.meshextrude3d_create(options).then((result: any) => {
        const loader = new GyMesh3dLoader();
        loader.load(result.FilePath).then(() => {
          const ac = new GyMesh3DActor(loader);
          ac.setRenderType(VTActorRenderType.SURFACE_WITH_EDGE);
          this.app.add(ac);
          this.clear_all_selected();
          resolve(true);
        });
      });
    });
  }

  // 扫掠
  async mesh_sweep_3d(options: Sweep3dOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      const {
        currentSelectedEdges,
        currentSelectedMeshIds,
        currentSelectedPartId,
      } = this.state;
      // if (currentSelectedMeshIds.size === 0 || currentSelectedEdges.size === 0) {
      //   reject(false);
      //   return
      // }
      const faces = [...currentSelectedMeshIds.values()].map((entityId) => ({
        entityFaceIndex: 0,
        entityId: entityId,
        entityType: 4, // 三维单元面是1024
        partId: currentSelectedPartId,
      }));
      const pathes = [...currentSelectedEdges.values()].map(
        ({ partId, edgeId }) => ({
          entityId: edgeId,
          partId,
          entityType: ENTITY_TYPE.EDGE,
        })
      );
      const path = pathes[0] || { entityId: 3, entityType: 8, partId: 1 };
      this.connector
        .mesh_sweep_3d({ ...options, faces, path })
        .then((result: any) => {
          const loader = new GyMesh3dLoader();
          loader.load(result.FilePath).then(() => {
            const ac = new GyMesh3DActor(loader);
            ac.setRenderType(VTActorRenderType.SURFACE_WITH_EDGE);
            this.app.add(ac);
            this.clear_all_selected();
            resolve(true);
          });
        });
    });
  }

  // 节点缝合
  async pastenode_apply(options: PastenodeApplyOptions): Promise<any> {
    return new Promise((resolve) => {
      this.connector.pastenode_apply(options).then((result: any) => {
        this.parent.selectBoxComp.resetSelectedMeshPoint();
        this.state.currentSelectedMeshPointIds.clear();
        this.state.currentSelectedMeshPointIdMapPartId.clear();
        this.app.currentSelectMeshPointId = -1;
        get_string_from_oss(this, result.fileName).then((json: string) => {
          this.mesh_update(this, json, 4, [0, 0, 1]);
          // this.clear_all_selected();
          resolve(true);
        });
      });
    });
  }
  async pastenode_add_nodes(option: {
    name: string;
    pointIds?: any[];
  }): Promise<any> {
    return new Promise((resolve, reject) => {
      const {
        currentSelectedMeshPointIds,
        currentSelectedMeshPointIdMapPartId,
      } = this.state;
      if (currentSelectedMeshPointIds.size === 0) {
        reject(false);
        return;
      }
      const nodeIds = !option.pointIds
        ? [...currentSelectedMeshPointIds.values()]
        : [...currentSelectedMeshPointIds.values()].filter(
            (nodeId) => option.pointIds && !option.pointIds.includes(nodeId)
          );
      const nodes = nodeIds.map((nodeId) => ({
        entityId: nodeId,
        partId: currentSelectedMeshPointIdMapPartId.get(nodeId),
      }));
      this.connector
        .pastenode_add_nodes({ setName: option.name, nodes })
        .then((result: boolean) => {
          resolve({ result, nodeIds });
        });
    });
  }
  async pastenode_enter(options: string): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.pastenode_enter(options).then((result: boolean) => {
        this.clear_all_selected();
        resolve(result);
      });
    });
  }
  async pastenode_leave(options?: string): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.pastenode_leave(options).then((result: boolean) => {
        this.clear_all_selected();
        this.parent.selectBoxComp.resetSelectedMeshPoint();
        this.state.currentSelectedMeshPointIds.clear();
        this.state.currentSelectedMeshPointIdMapPartId.clear();
        this.app.currentSelectMeshPointId = -1;
        resolve(result);
      });
    });
  }
  async pastenode_clear(options?: string): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.pastenode_clear(options).then((result: boolean) => {
        this.clear_all_selected();
        this.parent.selectBoxComp.resetSelectedMeshPoint();
        this.state.currentSelectedMeshPointIds.clear();
        this.state.currentSelectedMeshPointIdMapPartId.clear();
        this.app.currentSelectMeshPointId = -1;
        resolve(result);
      });
    });
  }
  // 转换
  async transform_leave(option: string): Promise<boolean> {
    return new Promise((resolve) => {
      this.connector.transform_leave(option).then((result: boolean) => {
        this.clear_all_selected();
        resolve(result);
      });
    });
  }
  async transform_update(options: TransformUpdateOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      const { currentSelectedParts } = this.state;
      if (currentSelectedParts.length == 0) {
        reject(false);
        return;
      }
      this.connector
        .transform_update({ param: options, parts: currentSelectedParts })
        .then((result: FIleLoadRes) => {
          try {
            this.app.actorList.foreach((ele: any) => {
              if (!(ele instanceof MeshActor && ele.isDpMesh == false)) {
                this.parent.ModelComp.engine.model.remove(ele);
              }
            });
            this.load_file_from_S3(result);
            resolve(result.BomInfo);
          } catch (err) {
            console.error("Error downloading file:", err);
          }
        });
    });
  }
  async freebody_read_file(options: FreebodyReadFileOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      this.connector.freebody_read_file(options).then((result: any) => {
        resolve(result);
      });
    });
  }
  async freebody_enter(options: FreebodyEnterOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      this.connector.freebody_enter(options).then((result: any) => {
        console.log("----> freebody_enter: ", result);
        resolve(result);
      });
    });
  }
  async freebody_leave(options: string): Promise<any> {
    return new Promise((resolve, reject) => {
      this.connector.freebody_leave(options).then((result: any) => {
        resolve(result);
      });
    });
  }
  async freebody_sets(): Promise<any> {
    return new Promise((resolve, reject) => {
      this.connector.freebody_sets().then((result: any) => {
        resolve(result);
      });
    });
  }
  async freebody_update_entities(options: FreebodyEntity[]): Promise<any> {
    return new Promise((resolve, reject) => {
      this.connector.freebody_update_entities(options).then((result: any) => {
        resolve(result);
      });
    });
  }
  async freebody_find_nodes(options: FreebodyFindNodesOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      this.connector.freebody_find_nodes(options).then((result: any) => {
        const { interfaceNodes } = result;
        const points = [];
        if (interfaceNodes && interfaceNodes.length) {
          this.app.actorList.foreach((ac) => {
            if (ac instanceof MeshActor) {
              ac.meshPointData.data.forEach((item) => {
                if (interfaceNodes.includes(item.nodeId)) {
                  const point = new PointerActor([item.x, item.y, item.z], {
                    color: [1, 0, 0],
                    radius: 1,
                  });
                  this.parent.model.add(point);
                  points.push(point);
                }
              });
            }
          });
        }
        resolve(points);
      });
    });
  }
  async freebody_apply(options: FreebodyApplyOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      const {
        currentSelectedMeshPointIds,
        currentSelectedMeshPointIdMapPartId,
      } = this.state;
      if (
        options.autoFindInterfaceNodes === 0 &&
        currentSelectedMeshPointIds.size === 0
      ) {
        reject(false);
        return;
      }
      const nodes = [...currentSelectedMeshPointIds.values()].map((nodeId) => ({
        entityId: nodeId,
        partId: currentSelectedMeshPointIdMapPartId.get(nodeId),
      }));
      this.connector
        .freebody_apply({ ...options, nodes })
        .then((result: any) => {
          // console.log("----> freebody sets: ", result);
          // this.clear_all_selected();
          this.parent.selectBoxComp.resetSelectedMeshPoint();
          this.state.currentSelectedMeshPointIds.clear();
          this.state.currentSelectedMeshPointIdMapPartId.clear();
          this.app.currentSelectMeshPointId = -1;
          resolve(result);
        });
    });
  }
  async freebody_table_data(options: FreebodyTableDataOptions): Promise<any> {
    return new Promise((resolve, reject) => {
      this.connector
        .freebody_table_data(options.fileName)
        .then((result: any) => {
          // console.log("----> table_data: ", result);
          resolve(result);
          // 创建载荷约束
          if (
            options.createLoadBCs &&
            result.op2Info &&
            result.op2Info.length
          ) {
            const nodeId_point: { [key: number]: number } = {};
            const pointsData: Array<[number, number, number]> = [];
            result.op2Info.forEach((item) => {
              item.nodeId.forEach((nodeId) => {
                nodeId_point[nodeId] = 1;
              });
            });
            this.app.actorList.foreach((ac) => {
              if (ac instanceof MeshActor) {
                ac.meshPointData.data.forEach((item) => {
                  if (nodeId_point[item.nodeId]) {
                    pointsData.push([item.x, item.y, item.z]);
                  }
                });
              }
            });
            // const suffix = options.var === 'force' ? 'Force' : 'Displacement';
            if (options.var === "force") {
              pointsData.forEach((pointData) => {
                const arrow = new TArrow([1, 1, 1], pointData);
                this.parent.model.add(arrow);
              });
            } else {
              const dof1 = new TCell([1, 0, 0], [1, 0, 0], pointsData);
              const dof2 = new TCell([0, 1, 0], [0, 1, 0], pointsData);
              const dof3 = new TCell([0, 0, 1], [0, 0, 1], pointsData);
              const dof4 = new TCell([1, 0, 0], [0.5, 0.5, 0.5], dof1.dofNext);
              const dof5 = new TCell([0, 1, 0], [0.5, 0.5, 0.5], dof2.dofNext);
              const dof6 = new TCell([0, 0, 1], [0.5, 0.5, 0.5], dof3.dofNext);
              this.parent.model.add(dof1);
              this.parent.model.add(dof2);
              this.parent.model.add(dof3);
              this.parent.model.add(dof4);
              this.parent.model.add(dof5);
              this.parent.model.add(dof6);
            }
          }
        });
    });
  }

  // 隐藏所有网格
  hide_all_mesh() {
    // 调用隐藏所有网格的函数
    func_hide_all_mesh(this);
  }

  // 显示所有网格
  show_all_mesh() {
    // 调用func_show_all_mesh函数，传入this参数
    func_show_all_mesh(this);
  }
  find_load_by_elem() {
    const meshIds = Array.from(this.state.currentSelectedMeshIds);
    const partId = (this.state.currentSelectedActors.value[0] as GyActor)
      .partId;
    return new Promise((resolve) => {
      this.connector.find_load_by_elem(meshIds, partId).then((res: any) => {
        resolve(res);
      });
    });
  }

  normal_get(ids: number[]) {
    return normal_get(this, ids);
  }

  normal_reverse(ids: number[]) {
    return normal_reverse(this, ids);
  }

  normal_align(ids: number[]) {
    return normal_align(this, ids);
  }

  show_normal(
    eids: number[],
    normals: number[],
    factor?: number,
    color?: number[]
  ) {
    if (this.normalActor !== null) return;
    let targetAc: MeshActor | null = null;
    this.app.actorList.foreach((actor: any) => {
      if ((actor as MeshActor).MESH_ACTOR) {
        targetAc = actor as MeshActor;
        return false;
      }
    });
    if (!targetAc) return;
    const indexes = (targetAc as MeshActor).transferCellIdsToIndexes(eids);
    const centers: number[] = [];
    indexes.forEach((index) => {
      const vec = (targetAc as MeshActor).cellCenterArr[index];
      centers.push(vec.x, vec.y, vec.z);
    });
    this.normalActor = new NormalActor(centers, normals);
    if (factor) {
      this.normalActor.setScaleFactor(factor);
    }
    if (color) {
      this.normalActor.setColor(color);
    }
    this.app.add(this.normalActor);
  }

  hide_normal() {
    if (!this.normalActor) return;
    this.app.remove(this.normalActor);
    this.normalActor = null;
  }
  // 检查重复的二维单元
  check_deplicate_elem() {
    const meshIds = Array.from(this.state.currentSelectedMeshIds);
    const partId = (this.state.currentSelectedActors.value[0] as GyActor)
      .partId;
    return new Promise((resolve) => {
      this.connector
        .check_deplicate_elem(meshIds, partId)
        .then((result: any) => {
          get_string_from_oss(this, result.File.fileName)
            .then((json: string) => {
              this.mesh_update(this, json, 4, [0, 0, 1]);
              this.clear_all_selected();
            })
            .then(() => {
              get_string_from_oss(this, result.Dp)
                .then((json: string) => {
                  this.dp_mesh_update(this, json, 8, [0, 1, 0]);
                })
                .then(() => {
                  get_string_from_oss(this, result.BomInfo).then((str) => {
                    resolve({
                      bomInfo: JSON.parse(str),
                      msg: result.Msg,
                    });
                  });
                });
            });
        });
    });
  }
  // 删除重复的二维单元
  delete_deplicate_elem(params: any) {
    this.parent.meshComp.deleteDpMesh();
    return new Promise((resolve) => {
      this.connector.delete_deplicate_elem(params).then((result: any) => {
        get_string_from_oss(this, result.BomInfo).then((str) => {
          resolve({
            bomInfo: JSON.parse(str),
          });
        });
      });
    });
  }

  /**
   * @abstract 执行修剪动作：修剪线、面、实体等
   * @param options 剪切参数
   * @param type 类型
   * @param target 目标实体对象（part_id + entity_id）
   * @param trim 修剪工具对象（part_id + entity_id）
   * @returns {Promise<Json>} bomInfo
   */
  async performTrim(
    options: any,
    type: string,
    target: { entity_id: number; part_id: number },
    trim: { entity_id: number; part_id: number }
  ) {
    return new Promise((resolve) => {
      this.connector
        .trim({
          target: target,
          trim: trim,
          options: options,
          type: type,
        })
        .then((res: FIleLoadRes) => {
          this.app.actorList.foreach(this.parent.ModelComp.engine.model.remove);
          this.load_file_from_S3(res);
          this.state.reset();
          // bom info
          get_string_from_oss(this, res.BomInfo).then((str) => {
            resolve(JSON.parse(str));
          });
          this.clear_selected_state();
          this.clear_all_selected();
          this.app.window.render();
        });
    });
  }

  private performTrimOperation(
    options: any,
    operationType: string,
    targetGetter: () => any,
    trimGetter: () => any
  ) {
    const target = targetGetter();
    const trim = trimGetter();
    return this.performTrim(options, operationType, target, trim);
  }

  // 线-切割-面
  trim_face_by_line(options: any) {
    return this.performTrimOperation(
      options,
      "trim_face_by_line",
      () => get_selected_face(this),
      () => get_selected_edge(this)
    );
  }

  // 面-切割-实体
  trim_body_by_face(options: any) {
    return this.performTrimOperation(
      options,
      "trim_body_by_face",
      () => get_selected_body(this),
      () => get_selected_face(this)
    );
  }

  // 面-切割-面
  trim_face_by_face(options: any) {
    const obj = get_selected_2_faces(this);
    return this.performTrim(options, "trim_face_by_face", obj.target, obj.trim);
  }

  // 点-切割-线
  trim_line_by_node(options: any) {
    return this.performTrimOperation(
      options,
      "trim_line_by_node",
      () => get_selected_edge(this),
      () => get_selected_node(this)
    );
  }

  mesh_quality(type: string, threshold: number) {
    return this.connector.mesh_quality(type, threshold);
  }

  changeFaceColor() {
    // console.log("changeFaceColorByNodeInfo:", nodeInfo);
    this.app.actorList.foreach((ac: any) => {
      if (ac instanceof MeshActor && !ac.isDpMesh) {
        const cellIds = ac.getCellIds(); // 获取所有网格单元ID
        cellIds.forEach((cellId) => {
          ac.setCellColor(cellId - 1, [0, 0, 205, 255]);
        });
      }
    });
    this.app.window.render();
  }

  clearFaceColor() {
    // console.log("changeFaceColorByNodeInfo:", nodeInfo);
    this.app.actorList.foreach((ac: any) => {
      if (ac instanceof MeshActor && !ac.isDpMesh) {
        const cellIds = ac.getCellIds(); // 获取所有网格单元ID
        cellIds.forEach((cellId) => {
          ac.setCellColor(cellId - 1, [255, 255, 0, 0]);
        });
      }
    });
    this.app.window.render();
  }
}
